From f16bd35d3cf63a099bd60deb759a2c44700f09b4 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 20 May 2022 12:20:50 +0100 Subject: [PATCH 01/24] Remove old ref-counted extern support from compiler-cranelift It was never fully implemented and we're moving to a different way of tracking ExternRef lifetimes. --- lib/compiler-cranelift/src/func_environ.rs | 91 +--- .../src/translator/code_translator.rs | 391 +++++++----------- .../src/translator/func_environ.rs | 17 - .../src/translator/func_state.rs | 74 +--- .../src/translator/func_translator.rs | 19 - lib/types/src/vmoffsets.rs | 8 - lib/vm/src/libcalls.rs | 27 +- lib/vm/src/vmcontext.rs | 4 - 8 files changed, 176 insertions(+), 455 deletions(-) diff --git a/lib/compiler-cranelift/src/func_environ.rs b/lib/compiler-cranelift/src/func_environ.rs index 96c627d9a80..afb6010d4d9 100644 --- a/lib/compiler-cranelift/src/func_environ.rs +++ b/lib/compiler-cranelift/src/func_environ.rs @@ -11,7 +11,7 @@ use cranelift_codegen::ir::immediates::{Offset32, Uimm64}; use cranelift_codegen::ir::types::*; use cranelift_codegen::ir::{AbiParam, ArgumentPurpose, Function, InstBuilder, Signature}; use cranelift_codegen::isa::TargetFrontendConfig; -use cranelift_frontend::{FunctionBuilder, Variable}; +use cranelift_frontend::FunctionBuilder; use std::convert::TryFrom; use wasmer_compiler::wasmparser::Type; use wasmer_types::entity::EntityRef; @@ -104,11 +104,6 @@ pub struct FuncEnvironment<'module_environment> { /// The external function signature for implementing wasm's `table.fill`. table_fill_sig: Option, - /// The external function signature for implementing reference increment for `extern.ref`. - externref_inc_sig: Option, - - /// The external function signature for implementing reference decrement for `extern.ref`. - externref_dec_sig: Option, /// Offsets to struct fields accessed by JIT code. offsets: VMOffsets, @@ -148,8 +143,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> { data_drop_sig: None, func_ref_sig: None, table_fill_sig: None, - externref_inc_sig: None, - externref_dec_sig: None, offsets: VMOffsets::new(target_config.pointer_bytes(), module), memory_styles, table_styles, @@ -202,50 +195,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> { ) } - fn get_externref_inc_sig(&mut self, func: &mut Function) -> ir::SigRef { - let sig = self.externref_inc_sig.unwrap_or_else(|| { - func.import_signature(Signature { - params: vec![AbiParam::new(R64)], - returns: vec![], - call_conv: self.target_config.default_call_conv, - }) - }); - self.externref_inc_sig = Some(sig); - sig - } - - fn get_externref_inc_func( - &mut self, - func: &mut Function, - ) -> (ir::SigRef, VMBuiltinFunctionIndex) { - ( - self.get_externref_inc_sig(func), - VMBuiltinFunctionIndex::get_externref_inc_index(), - ) - } - - fn get_externref_dec_sig(&mut self, func: &mut Function) -> ir::SigRef { - let sig = self.externref_dec_sig.unwrap_or_else(|| { - func.import_signature(Signature { - params: vec![AbiParam::new(R64)], - returns: vec![], - call_conv: self.target_config.default_call_conv, - }) - }); - self.externref_dec_sig = Some(sig); - sig - } - - fn get_externref_dec_func( - &mut self, - func: &mut Function, - ) -> (ir::SigRef, VMBuiltinFunctionIndex) { - ( - self.get_externref_dec_sig(func), - VMBuiltinFunctionIndex::get_externref_dec_index(), - ) - } - fn get_func_ref_sig(&mut self, func: &mut Function) -> ir::SigRef { let sig = self.func_ref_sig.unwrap_or_else(|| { func.import_signature(Signature { @@ -902,32 +851,6 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro Ok(()) } - fn translate_externref_inc( - &mut self, - mut pos: cranelift_codegen::cursor::FuncCursor<'_>, - externref: ir::Value, - ) -> WasmResult<()> { - let (func_sig, func_idx) = self.get_externref_inc_func(pos.func); - let (_vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx); - - pos.ins().call_indirect(func_sig, func_addr, &[externref]); - - Ok(()) - } - - fn translate_externref_dec( - &mut self, - mut pos: cranelift_codegen::cursor::FuncCursor<'_>, - externref: ir::Value, - ) -> WasmResult<()> { - let (func_sig, func_idx) = self.get_externref_dec_func(pos.func); - let (_vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx); - - pos.ins().call_indirect(func_sig, func_addr, &[externref]); - - Ok(()) - } - fn translate_ref_null( &mut self, mut pos: cranelift_codegen::cursor::FuncCursor, @@ -1524,16 +1447,4 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro fn get_function_sig(&self, sig_index: SignatureIndex) -> Option<&FunctionType> { self.module.signatures.get(sig_index) } - - fn translate_drop_locals(&mut self, builder: &mut FunctionBuilder) -> WasmResult<()> { - // TODO: this allocation can be removed without too much effort but it will require - // maneuvering around the borrow checker - for (local_index, local_type) in self.type_stack.to_vec().iter().enumerate() { - if *local_type == WasmerType::ExternRef { - let val = builder.use_var(Variable::with_u32(local_index as _)); - self.translate_externref_dec(builder.cursor(), val)?; - } - } - Ok(()) - } } diff --git a/lib/compiler-cranelift/src/translator/code_translator.rs b/lib/compiler-cranelift/src/translator/code_translator.rs index 99d1a57ba55..c750d6c3231 100644 --- a/lib/compiler-cranelift/src/translator/code_translator.rs +++ b/lib/compiler-cranelift/src/translator/code_translator.rs @@ -75,7 +75,7 @@ //! ("Relax verification to allow I8X16 to act as a default vector type") use super::func_environ::{FuncEnvironment, GlobalVariable, ReturnMode}; -use super::func_state::{ControlStackFrame, ElseData, FuncTranslationState, ValueExtraInfo}; +use super::func_state::{ControlStackFrame, ElseData, FuncTranslationState}; use super::translation_utils::{block_with_params, f32_translation, f64_translation}; use crate::{hash_map, HashMap}; use core::cmp; @@ -92,11 +92,10 @@ use cranelift_frontend::{FunctionBuilder, Variable}; use smallvec::SmallVec; use std::vec::Vec; -use wasmer_compiler::wasmparser::{MemoryImmediate, Operator, Type as WPType}; +use wasmer_compiler::wasmparser::{MemoryImmediate, Operator}; use wasmer_compiler::{from_binaryreadererror_wasmerror, wasm_unsupported, ModuleTranslationState}; use wasmer_types::{ - FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex, Type as WasmerType, - WasmResult, + FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex, WasmResult, }; // Clippy warns about "align: _" but its important to document that the align field is ignored @@ -126,25 +125,13 @@ pub fn translate_operator( ***********************************************************************************/ Operator::LocalGet { local_index } => { let val = builder.use_var(Variable::with_u32(*local_index)); - let local_type = environ.get_local_type(*local_index).unwrap(); - let ref_counted = local_type == WasmerType::ExternRef; - state.push1_extra((val, ValueExtraInfo { ref_counted })); + state.push1(val); let label = ValueLabel::from_u32(*local_index); builder.set_val_label(val, label); - - if ref_counted { - environ.translate_externref_inc(builder.cursor(), val)?; - } } Operator::LocalSet { local_index } => { - let (mut val, _metadata) = state.pop1(); + let mut val = state.pop1(); - let local_type = environ.get_local_type(*local_index).unwrap(); - if local_type == WasmerType::ExternRef { - debug_assert!(_metadata.ref_counted); - let existing_val = builder.use_var(Variable::with_u32(*local_index)); - environ.translate_externref_dec(builder.cursor(), existing_val)?; - } // Ensure SIMD values are cast to their default Cranelift type, I8x16. let ty = builder.func.dfg.value_type(val); if ty.is_vector() { @@ -156,16 +143,8 @@ pub fn translate_operator( builder.set_val_label(val, label); } Operator::LocalTee { local_index } => { - let (mut val, _metadata) = state.peek1(); - - // ref count if we need to - let local_type = environ.get_local_type(*local_index).unwrap(); - if local_type == WasmerType::ExternRef { - debug_assert!(_metadata.ref_counted); - let existing_val = builder.use_var(Variable::with_u32(*local_index)); - environ.translate_externref_dec(builder.cursor(), existing_val)?; - environ.translate_externref_inc(builder.cursor(), val)?; - } + let mut val = state.peek1(); + // Ensure SIMD values are cast to their default Cranelift type, I8x16. let ty = builder.func.dfg.value_type(val); if ty.is_vector() { @@ -182,25 +161,17 @@ pub fn translate_operator( Operator::GlobalGet { global_index } => { let global_index = GlobalIndex::from_u32(*global_index); let stack_elem = match state.get_global(builder.func, global_index.as_u32(), environ)? { - GlobalVariable::Const(val) => (val, ValueExtraInfo::default()), + GlobalVariable::Const(val) => val, GlobalVariable::Memory { gv, offset, ty } => { - let global_type = environ.get_global_type(global_index).unwrap(); let addr = builder.ins().global_value(environ.pointer_type(), gv); let flags = ir::MemFlags::trusted(); - let value = builder.ins().load(ty, flags, addr, offset); - let ref_counted = global_type == WasmerType::ExternRef; - if ref_counted { - environ.translate_externref_inc(builder.cursor(), value)?; - } - - (value, ValueExtraInfo { ref_counted }) + builder.ins().load(ty, flags, addr, offset) + } + GlobalVariable::Custom => { + environ.translate_custom_global_get(builder.cursor(), global_index)? } - GlobalVariable::Custom => ( - environ.translate_custom_global_get(builder.cursor(), global_index)?, - ValueExtraInfo::default(), - ), }; - state.push1_extra(stack_elem); + state.push1(stack_elem); } Operator::GlobalSet { global_index } => { let global_index = GlobalIndex::from_u32(*global_index); @@ -209,23 +180,18 @@ pub fn translate_operator( panic!("global #{} is a constant", global_index.as_u32()) } GlobalVariable::Memory { gv, offset, ty } => { - let global_type = environ.get_global_type(global_index).unwrap(); let addr = builder.ins().global_value(environ.pointer_type(), gv); let flags = ir::MemFlags::trusted(); - let (mut val, _) = state.pop1(); + let mut val = state.pop1(); // Ensure SIMD values are cast to their default Cranelift type, I8x16. if ty.is_vector() { val = optionally_bitcast_vector(val, I8X16, builder); } debug_assert_eq!(ty, builder.func.dfg.value_type(val)); - if global_type == WasmerType::ExternRef { - let value = builder.ins().load(ty, flags, addr, offset); - environ.translate_externref_dec(builder.cursor(), value)?; - } builder.ins().store(flags, val, addr, offset); } GlobalVariable::Custom => { - let (val, _) = state.pop1(); + let val = state.pop1(); environ.translate_custom_global_set(builder.cursor(), global_index, val)?; } } @@ -234,14 +200,11 @@ pub fn translate_operator( * `drop`, `nop`, `unreachable` and `select`. ***********************************************************************************/ Operator::Drop => { - let (val, metadata) = state.pop1(); - if metadata.ref_counted { - environ.translate_externref_dec(builder.cursor(), val)?; - } + state.pop1(); } Operator::Select => { // we can ignore metadata because extern ref must use TypedSelect - let ((mut arg1, _), (mut arg2, _), (cond, _)) = state.pop3(); + let (mut arg1, mut arg2, cond) = state.pop3(); if builder.func.dfg.value_type(arg1).is_vector() { arg1 = optionally_bitcast_vector(arg1, I8X16, builder); } @@ -250,20 +213,9 @@ pub fn translate_operator( } state.push1(builder.ins().select(cond, arg1, arg2)); } - Operator::TypedSelect { ty } => { - let ((arg1, _), (arg2, _), (cond, _)) = state.pop3(); - let ref_counted = *ty == WPType::ExternRef; - if ref_counted { - let selected_ref = builder.ins().select(cond, arg1, arg2); - let not_selected_ref = builder.ins().select(cond, arg2, arg1); - state.push1_extra((selected_ref, ValueExtraInfo { ref_counted })); - environ.translate_externref_dec(builder.cursor(), not_selected_ref)?; - } else { - state.push1_extra(( - builder.ins().select(cond, arg1, arg2), - ValueExtraInfo::default(), - )); - } + Operator::TypedSelect { ty: _ } => { + let (arg1, arg2, cond) = state.pop3(); + state.push1(builder.ins().select(cond, arg1, arg2)); } Operator::Nop => { // We do nothing @@ -306,7 +258,7 @@ pub fn translate_operator( environ.translate_loop_header(builder.cursor())?; } Operator::If { ty } => { - let (val, _) = state.pop1(); + let val = state.pop1(); let (params, results) = module_translation_state.blocktype_params_results(*ty)?; let (destination, else_data) = if params == results { @@ -331,7 +283,7 @@ pub fn translate_operator( }; let next_block = builder.create_block(); - canonicalise_then_jump(builder, next_block, (&[], &[])); + canonicalise_then_jump(builder, next_block, &[]); builder.seal_block(next_block); // Only predecessor is the current block. builder.switch_to_block(next_block); @@ -500,7 +452,7 @@ pub fn translate_operator( min_depth_frame.num_return_values() } }; - let (val, _) = state.pop1(); + let val = state.pop1(); let mut data = JumpTableData::with_capacity(table.len() as usize); if jump_args_count == 0 { // No jump arguments @@ -576,7 +528,7 @@ pub fn translate_operator( (return_count, frame.br_destination()) }; { - let (return_args, return_args_metadata) = state.peekn_mut(return_count); + let return_args = state.peekn_mut(return_count); // TODO(reftypes): maybe ref count here? let return_types = wasm_param_types(&builder.func.signature.returns, |i| { environ.is_wasm_return(&builder.func.signature, i) @@ -584,11 +536,9 @@ pub fn translate_operator( bitcast_arguments(return_args, &return_types, builder); match environ.return_mode() { ReturnMode::NormalReturns => builder.ins().return_(return_args), - ReturnMode::FallthroughReturn => canonicalise_then_jump( - builder, - br_destination, - (&*return_args, &*return_args_metadata), - ), + ReturnMode::FallthroughReturn => { + canonicalise_then_jump(builder, br_destination, return_args) + } }; } state.popn(return_count); @@ -614,7 +564,7 @@ pub fn translate_operator( Operator::Call { function_index } => { let (fref, num_args) = state.get_direct_func(builder.func, *function_index, environ)?; - let (args, _args_metadata) = state.peekn_mut(num_args); + let args = state.peekn_mut(num_args); // Bitcast any vector arguments to their default type, I8X16, before calling. let callee_signature = @@ -634,34 +584,25 @@ pub fn translate_operator( .len(), "translate_call results should match the call signature" ); - let func_type = environ.get_function_type(func_index).unwrap(); - let mut results_metadata = Vec::with_capacity(func_type.results().len()); - for result in func_type.results() { - results_metadata.push(if *result == WasmerType::ExternRef { - ValueExtraInfo { ref_counted: true } - } else { - Default::default() - }); - } state.popn(num_args); - state.pushn(inst_results, &results_metadata); + state.pushn(inst_results); } Operator::CallIndirect { index, table_index } => { // `index` is the index of the function's signature and `table_index` is the index of // the table to search the function in. let (sigref, num_args) = state.get_indirect_sig(builder.func, *index, environ)?; let table = state.get_or_create_table(builder.func, *table_index, environ)?; - let (callee, _) = state.pop1(); + let callee = state.pop1(); // Bitcast any vector arguments to their default type, I8X16, before calling. let callee_signature = &builder.func.dfg.signatures[sigref]; - let (args, _) = state.peekn_mut(num_args); + let args = state.peekn_mut(num_args); let types = wasm_param_types(&callee_signature.params, |i| { environ.is_wasm_parameter(callee_signature, i) }); bitcast_arguments(args, &types, builder); - let (args, _args_metadata) = state.peekn(num_args); + let args = state.peekn(num_args); let sig_idx = SignatureIndex::from_u32(*index); let call = environ.translate_call_indirect( @@ -679,17 +620,8 @@ pub fn translate_operator( builder.func.dfg.signatures[sigref].returns.len(), "translate_call_indirect results should match the call signature" ); - let func_type = environ.get_function_sig(sig_idx).unwrap(); - let mut results_metadata = Vec::with_capacity(func_type.results().len()); - for result in func_type.results() { - results_metadata.push(if *result == WasmerType::ExternRef { - ValueExtraInfo { ref_counted: true } - } else { - Default::default() - }); - } state.popn(num_args); - state.pushn(inst_results, &results_metadata); + state.pushn(inst_results); } /******************************* Memory management *********************************** * Memory management is handled by environment. It is usually translated into calls to @@ -700,7 +632,7 @@ pub fn translate_operator( // argument to be a memory index. let heap_index = MemoryIndex::from_u32(*mem); let heap = state.get_heap(builder.func, *mem, environ)?; - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(environ.translate_memory_grow(builder.cursor(), heap_index, heap, val)?) } Operator::MemorySize { mem, mem_byte: _ } => { @@ -820,246 +752,246 @@ pub fn translate_operator( } /******************************* Unary Operators *************************************/ Operator::I32Clz | Operator::I64Clz => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().clz(arg)); } Operator::I32Ctz | Operator::I64Ctz => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().ctz(arg)); } Operator::I32Popcnt | Operator::I64Popcnt => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().popcnt(arg)); } Operator::I64ExtendI32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().sextend(I64, val)); } Operator::I64ExtendI32U => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().uextend(I64, val)); } Operator::I32WrapI64 => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().ireduce(I32, val)); } Operator::F32Sqrt | Operator::F64Sqrt => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().sqrt(arg)); } Operator::F32Ceil | Operator::F64Ceil => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().ceil(arg)); } Operator::F32Floor | Operator::F64Floor => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().floor(arg)); } Operator::F32Trunc | Operator::F64Trunc => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().trunc(arg)); } Operator::F32Nearest | Operator::F64Nearest => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().nearest(arg)); } Operator::F32Abs | Operator::F64Abs => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fabs(val)); } Operator::F32Neg | Operator::F64Neg => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); state.push1(builder.ins().fneg(arg)); } Operator::F64ConvertI64U | Operator::F64ConvertI32U => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_from_uint(F64, val)); } Operator::F64ConvertI64S | Operator::F64ConvertI32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_from_sint(F64, val)); } Operator::F32ConvertI64S | Operator::F32ConvertI32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_from_sint(F32, val)); } Operator::F32ConvertI64U | Operator::F32ConvertI32U => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_from_uint(F32, val)); } Operator::F64PromoteF32 => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fpromote(F64, val)); } Operator::F32DemoteF64 => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fdemote(F32, val)); } Operator::I64TruncF64S | Operator::I64TruncF32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_sint(I64, val)); } Operator::I32TruncF64S | Operator::I32TruncF32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_sint(I32, val)); } Operator::I64TruncF64U | Operator::I64TruncF32U => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_uint(I64, val)); } Operator::I32TruncF64U | Operator::I32TruncF32U => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_uint(I32, val)); } Operator::I64TruncSatF64S | Operator::I64TruncSatF32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_sint_sat(I64, val)); } Operator::I32TruncSatF64S | Operator::I32TruncSatF32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_sint_sat(I32, val)); } Operator::I64TruncSatF64U | Operator::I64TruncSatF32U => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_uint_sat(I64, val)); } Operator::I32TruncSatF64U | Operator::I32TruncSatF32U => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().fcvt_to_uint_sat(I32, val)); } Operator::F32ReinterpretI32 => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().bitcast(F32, val)); } Operator::F64ReinterpretI64 => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().bitcast(F64, val)); } Operator::I32ReinterpretF32 => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().bitcast(I32, val)); } Operator::I64ReinterpretF64 => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().bitcast(I64, val)); } Operator::I32Extend8S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().ireduce(I8, val)); - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().sextend(I32, val)); } Operator::I32Extend16S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().ireduce(I16, val)); - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().sextend(I32, val)); } Operator::I64Extend8S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().ireduce(I8, val)); - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().sextend(I64, val)); } Operator::I64Extend16S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().ireduce(I16, val)); - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().sextend(I64, val)); } Operator::I64Extend32S => { - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().ireduce(I32, val)); - let (val, _) = state.pop1(); + let val = state.pop1(); state.push1(builder.ins().sextend(I64, val)); } /****************************** Binary Operators ************************************/ Operator::I32Add | Operator::I64Add => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().iadd(arg1, arg2)); } Operator::I32And | Operator::I64And => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().band(arg1, arg2)); } Operator::I32Or | Operator::I64Or => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().bor(arg1, arg2)); } Operator::I32Xor | Operator::I64Xor => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().bxor(arg1, arg2)); } Operator::I32Shl | Operator::I64Shl => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().ishl(arg1, arg2)); } Operator::I32ShrS | Operator::I64ShrS => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().sshr(arg1, arg2)); } Operator::I32ShrU | Operator::I64ShrU => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().ushr(arg1, arg2)); } Operator::I32Rotl | Operator::I64Rotl => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().rotl(arg1, arg2)); } Operator::I32Rotr | Operator::I64Rotr => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().rotr(arg1, arg2)); } Operator::F32Add | Operator::F64Add => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().fadd(arg1, arg2)); } Operator::I32Sub | Operator::I64Sub => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().isub(arg1, arg2)); } Operator::F32Sub | Operator::F64Sub => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().fsub(arg1, arg2)); } Operator::I32Mul | Operator::I64Mul => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().imul(arg1, arg2)); } Operator::F32Mul | Operator::F64Mul => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().fmul(arg1, arg2)); } Operator::F32Div | Operator::F64Div => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().fdiv(arg1, arg2)); } Operator::I32DivS | Operator::I64DivS => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().sdiv(arg1, arg2)); } Operator::I32DivU | Operator::I64DivU => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().udiv(arg1, arg2)); } Operator::I32RemS | Operator::I64RemS => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().srem(arg1, arg2)); } Operator::I32RemU | Operator::I64RemU => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().urem(arg1, arg2)); } Operator::F32Min | Operator::F64Min => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().fmin(arg1, arg2)); } Operator::F32Max | Operator::F64Max => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().fmax(arg1, arg2)); } Operator::F32Copysign | Operator::F64Copysign => { - let ((arg1, _), (arg2, _)) = state.pop2(); + let (arg1, arg2) = state.pop2(); state.push1(builder.ins().fcopysign(arg1, arg2)); } /**************************** Comparison Operators **********************************/ @@ -1088,7 +1020,7 @@ pub fn translate_operator( translate_icmp(IntCC::UnsignedGreaterThanOrEqual, builder, state) } Operator::I32Eqz | Operator::I64Eqz => { - let (arg, _) = state.pop1(); + let arg = state.pop1(); let val = builder.ins().icmp_imm(IntCC::Equal, arg, 0); state.push1(builder.ins().bint(I32, val)); } @@ -1106,7 +1038,7 @@ pub fn translate_operator( } Operator::RefNull { ty } => state.push1(environ.translate_ref_null(builder.cursor(), *ty)?), Operator::RefIsNull => { - let (value, _) = state.pop1(); + let value = state.pop1(); state.push1(environ.translate_ref_is_null(builder.cursor(), value)?); } Operator::RefFunc { function_index } => { @@ -1124,9 +1056,9 @@ pub fn translate_operator( }; let heap_index = MemoryIndex::from_u32(memarg.memory); let heap = state.get_heap(builder.func, memarg.memory, environ)?; - let (timeout, _) = state.pop1(); // 64 (fixed) - let (expected, _) = state.pop1(); // 32 or 64 (per the `Ixx` in `IxxAtomicWait`) - let (addr, _) = state.pop1(); // 32 (fixed) + let timeout = state.pop1(); // 64 (fixed) + let expected = state.pop1(); // 32 or 64 (per the `Ixx` in `IxxAtomicWait`) + let addr = state.pop1(); // 32 (fixed) let addr = fold_atomic_mem_addr(addr, memarg, implied_ty, builder); assert!(builder.func.dfg.value_type(expected) == implied_ty); // `fn translate_atomic_wait` can inspect the type of `expected` to figure out what @@ -1144,8 +1076,8 @@ pub fn translate_operator( Operator::MemoryAtomicNotify { memarg } => { let heap_index = MemoryIndex::from_u32(memarg.memory); let heap = state.get_heap(builder.func, memarg.memory, environ)?; - let (count, _) = state.pop1(); // 32 (fixed) - let (addr, _) = state.pop1(); // 32 (fixed) + let count = state.pop1(); // 32 (fixed) + let addr = state.pop1(); // 32 (fixed) let addr = fold_atomic_mem_addr(addr, memarg, I32, builder); let res = environ.translate_atomic_notify(builder.cursor(), heap_index, heap, addr, count)?; @@ -1357,9 +1289,9 @@ pub fn translate_operator( let dst_index = MemoryIndex::from_u32(*dst); let src_heap = state.get_heap(builder.func, *src, environ)?; let dst_heap = state.get_heap(builder.func, *dst, environ)?; - let (len, _) = state.pop1(); - let (src_pos, _) = state.pop1(); - let (dst_pos, _) = state.pop1(); + let len = state.pop1(); + let src_pos = state.pop1(); + let dst_pos = state.pop1(); environ.translate_memory_copy( builder.cursor(), src_index, @@ -1374,17 +1306,17 @@ pub fn translate_operator( Operator::MemoryFill { mem } => { let heap_index = MemoryIndex::from_u32(*mem); let heap = state.get_heap(builder.func, *mem, environ)?; - let (len, _) = state.pop1(); - let (val, _) = state.pop1(); - let (dest, _) = state.pop1(); + let len = state.pop1(); + let val = state.pop1(); + let dest = state.pop1(); environ.translate_memory_fill(builder.cursor(), heap_index, heap, dest, val, len)?; } Operator::MemoryInit { segment, mem } => { let heap_index = MemoryIndex::from_u32(*mem); let heap = state.get_heap(builder.func, *mem, environ)?; - let (len, _) = state.pop1(); - let (src, _) = state.pop1(); - let (dest, _) = state.pop1(); + let len = state.pop1(); + let src = state.pop1(); + let dest = state.pop1(); environ.translate_memory_init( builder.cursor(), heap_index, @@ -1409,8 +1341,8 @@ pub fn translate_operator( Operator::TableGrow { table: index } => { let table_index = TableIndex::from_u32(*index); let table = state.get_or_create_table(builder.func, *index, environ)?; - let (delta, _) = state.pop1(); - let (init_value, _) = state.pop1(); + let delta = state.pop1(); + let init_value = state.pop1(); state.push1(environ.translate_table_grow( builder.cursor(), table_index, @@ -1422,7 +1354,7 @@ pub fn translate_operator( Operator::TableGet { table: index } => { let table_index = TableIndex::from_u32(*index); let table = state.get_or_create_table(builder.func, *index, environ)?; - let (index, _) = state.pop1(); + let index = state.pop1(); state.push1(environ.translate_table_get(builder, table_index, table, index)?); } Operator::TableSet { table: index } => { @@ -1430,8 +1362,8 @@ pub fn translate_operator( let table = state.get_or_create_table(builder.func, *index, environ)?; // We don't touch the ref count here because we're passing it to the host // then dropping it from the stack. Thus 1 + -1 = 0. - let (value, _) = state.pop1(); - let (index, _) = state.pop1(); + let value = state.pop1(); + let index = state.pop1(); environ.translate_table_set(builder, table_index, table, value, index)?; } Operator::TableCopy { @@ -1440,9 +1372,9 @@ pub fn translate_operator( } => { let dst_table = state.get_or_create_table(builder.func, *dst_table_index, environ)?; let src_table = state.get_or_create_table(builder.func, *src_table_index, environ)?; - let (len, _) = state.pop1(); - let (src, _) = state.pop1(); - let (dest, _) = state.pop1(); + let len = state.pop1(); + let src = state.pop1(); + let dest = state.pop1(); environ.translate_table_copy( builder.cursor(), TableIndex::from_u32(*dst_table_index), @@ -1456,9 +1388,9 @@ pub fn translate_operator( } Operator::TableFill { table } => { let table_index = TableIndex::from_u32(*table); - let (len, _) = state.pop1(); - let (val, _) = state.pop1(); - let (dest, _) = state.pop1(); + let len = state.pop1(); + let val = state.pop1(); + let dest = state.pop1(); environ.translate_table_fill(builder.cursor(), table_index, dest, val, len)?; } Operator::TableInit { @@ -1466,9 +1398,9 @@ pub fn translate_operator( table: table_index, } => { let table = state.get_or_create_table(builder.func, *table_index, environ)?; - let (len, _) = state.pop1(); - let (src, _) = state.pop1(); - let (dest, _) = state.pop1(); + let len = state.pop1(); + let src = state.pop1(); + let dest = state.pop1(); environ.translate_table_init( builder.cursor(), *segment, @@ -1491,9 +1423,7 @@ pub fn translate_operator( state.push1(value) } Operator::I8x16Splat | Operator::I16x8Splat => { - let reduced = builder - .ins() - .ireduce(type_of(op).lane_type(), state.pop1().0); + let reduced = builder.ins().ireduce(type_of(op).lane_type(), state.pop1()); let splatted = builder.ins().splat(type_of(op), reduced); state.push1(splatted) } @@ -1501,7 +1431,7 @@ pub fn translate_operator( | Operator::I64x2Splat | Operator::F32x4Splat | Operator::F64x2Splat => { - let splatted = builder.ins().splat(type_of(op), state.pop1().0); + let splatted = builder.ins().splat(type_of(op), state.pop1()); state.push1(splatted) } Operator::V128Load8Splat { memarg } @@ -1516,7 +1446,7 @@ pub fn translate_operator( state, environ, )?; - let splatted = builder.ins().splat(type_of(op), state.pop1().0); + let splatted = builder.ins().splat(type_of(op), state.pop1()); state.push1(splatted) } Operator::V128Load32Zero { memarg } | Operator::V128Load64Zero { memarg } => { @@ -1528,7 +1458,7 @@ pub fn translate_operator( state, environ, )?; - let as_vector = builder.ins().scalar_to_vector(type_of(op), state.pop1().0); + let as_vector = builder.ins().scalar_to_vector(type_of(op), state.pop1()); state.push1(as_vector) } Operator::V128Load8Lane { memarg, lane } @@ -1544,7 +1474,7 @@ pub fn translate_operator( state, environ, )?; - let replacement = state.pop1().0; + let replacement = state.pop1(); state.push1(builder.ins().insertlane(vector, replacement, *lane)) } Operator::V128Store8Lane { memarg, lane } @@ -1576,7 +1506,7 @@ pub fn translate_operator( state.push1(builder.ins().extractlane(vector, *lane)) } Operator::I8x16ReplaceLane { lane } | Operator::I16x8ReplaceLane { lane } => { - let ((vector, _), (replacement, _)) = state.pop2(); + let (vector, replacement) = state.pop2(); let ty = type_of(op); let reduced = builder.ins().ireduce(ty.lane_type(), replacement); let vector = optionally_bitcast_vector(vector, ty, builder); @@ -1586,7 +1516,7 @@ pub fn translate_operator( | Operator::I64x2ReplaceLane { lane } | Operator::F32x4ReplaceLane { lane } | Operator::F64x2ReplaceLane { lane } => { - let ((vector, _), (replacement, _)) = state.pop2(); + let (vector, replacement) = state.pop2(); let vector = optionally_bitcast_vector(vector, type_of(op), builder); state.push1(builder.ins().insertlane(vector, replacement, *lane)) } @@ -1678,11 +1608,11 @@ pub fn translate_operator( state.push1(builder.ins().band_not(a, b)) } Operator::V128Not => { - let (a, _) = state.pop1(); + let a = state.pop1(); state.push1(builder.ins().bnot(a)); } Operator::I8x16Shl | Operator::I16x8Shl | Operator::I32x4Shl | Operator::I64x2Shl => { - let ((a, _), (b, _)) = state.pop2(); + let (a, b) = state.pop2(); let bitcast_a = optionally_bitcast_vector(a, type_of(op), builder); let bitwidth = i64::from(type_of(op).lane_bits()); // The spec expects to shift with `b mod lanewidth`; so, e.g., for 16 bit lane-width @@ -1691,7 +1621,7 @@ pub fn translate_operator( state.push1(builder.ins().ishl(bitcast_a, b_mod_bitwidth)) } Operator::I8x16ShrU | Operator::I16x8ShrU | Operator::I32x4ShrU | Operator::I64x2ShrU => { - let ((a, _), (b, _)) = state.pop2(); + let (a, b) = state.pop2(); let bitcast_a = optionally_bitcast_vector(a, type_of(op), builder); let bitwidth = i64::from(type_of(op).lane_bits()); // The spec expects to shift with `b mod lanewidth`; so, e.g., for 16 bit lane-width @@ -1700,7 +1630,7 @@ pub fn translate_operator( state.push1(builder.ins().ushr(bitcast_a, b_mod_bitwidth)) } Operator::I8x16ShrS | Operator::I16x8ShrS | Operator::I32x4ShrS | Operator::I64x2ShrS => { - let ((a, _), (b, _)) = state.pop2(); + let (a, b) = state.pop2(); let bitcast_a = optionally_bitcast_vector(a, type_of(op), builder); let bitwidth = i64::from(type_of(op).lane_bits()); // The spec expects to shift with `b mod lanewidth`; so, e.g., for 16 bit lane-width @@ -1709,7 +1639,7 @@ pub fn translate_operator( state.push1(builder.ins().sshr(bitcast_a, b_mod_bitwidth)) } Operator::V128Bitselect => { - let ((a, _), (b, _), (c, _)) = state.pop3(); + let (a, b, c) = state.pop3(); let bitcast_a = optionally_bitcast_vector(a, I8X16, builder); let bitcast_b = optionally_bitcast_vector(b, I8X16, builder); let bitcast_c = optionally_bitcast_vector(c, I8X16, builder); @@ -2322,7 +2252,7 @@ fn prepare_load( state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<(MemFlags, Value, Offset32)> { - let (addr32, _) = state.pop1(); + let addr32 = state.pop1(); let heap = state.get_heap(builder.func, memarg.memory, environ)?; let (base, offset) = get_heap_addr( @@ -2373,7 +2303,7 @@ fn translate_store( state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { - let ((addr32, _), (val, _)) = state.pop2(); + let (addr32, val) = state.pop2(); let val_ty = builder.func.dfg.value_type(val); let heap = state.get_heap(builder.func, memarg.memory, environ)?; @@ -2405,7 +2335,7 @@ fn mem_op_size(opcode: ir::Opcode, ty: Type) -> u32 { } fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) { - let ((arg0, _), (arg1, _)) = state.pop2(); + let (arg0, arg1) = state.pop2(); let val = builder.ins().icmp(cc, arg0, arg1); state.push1(builder.ins().bint(I32, val)); } @@ -2498,7 +2428,7 @@ fn translate_atomic_rmw( state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { - let ((linear_mem_addr, _), (mut arg2, _)) = state.pop2(); + let (linear_mem_addr, mut arg2) = state.pop2(); let arg2_ty = builder.func.dfg.value_type(arg2); // The operation is performed at type `access_ty`, and the old value is zero-extended @@ -2544,7 +2474,7 @@ fn translate_atomic_cas( state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { - let ((linear_mem_addr, _), (mut expected, _), (mut replacement, _)) = state.pop3(); + let (linear_mem_addr, mut expected, mut replacement) = state.pop3(); let expected_ty = builder.func.dfg.value_type(expected); let replacement_ty = builder.func.dfg.value_type(replacement); @@ -2595,7 +2525,7 @@ fn translate_atomic_load( state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { - let (linear_mem_addr, _) = state.pop1(); + let linear_mem_addr = state.pop1(); // The load is performed at type `access_ty`, and the loaded value is zero extended // to `widened_ty`. @@ -2634,7 +2564,7 @@ fn translate_atomic_store( state: &mut FuncTranslationState, environ: &mut FE, ) -> WasmResult<()> { - let ((linear_mem_addr, _), (mut data, _)) = state.pop2(); + let (linear_mem_addr, mut data) = state.pop2(); let data_ty = builder.func.dfg.value_type(data); // The operation is performed at type `access_ty`, and the data to be stored may first @@ -2673,14 +2603,14 @@ fn translate_vector_icmp( builder: &mut FunctionBuilder, state: &mut FuncTranslationState, ) { - let ((a, _), (b, _)) = state.pop2(); + let (a, b) = state.pop2(); let bitcast_a = optionally_bitcast_vector(a, needed_type, builder); let bitcast_b = optionally_bitcast_vector(b, needed_type, builder); state.push1(builder.ins().icmp(cc, bitcast_a, bitcast_b)) } fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut FuncTranslationState) { - let ((arg0, _), (arg1, _)) = state.pop2(); + let (arg0, arg1) = state.pop2(); let val = builder.ins().fcmp(cc, arg0, arg1); state.push1(builder.ins().bint(I32, val)); } @@ -2691,7 +2621,7 @@ fn translate_vector_fcmp( builder: &mut FunctionBuilder, state: &mut FuncTranslationState, ) { - let ((a, _), (b, _)) = state.pop2(); + let (a, b) = state.pop2(); let bitcast_a = optionally_bitcast_vector(a, needed_type, builder); let bitcast_b = optionally_bitcast_vector(b, needed_type, builder); state.push1(builder.ins().fcmp(cc, bitcast_a, bitcast_b)) @@ -2702,13 +2632,12 @@ fn translate_br_if( builder: &mut FunctionBuilder, state: &mut FuncTranslationState, ) { - let (val, _) = state.pop1(); + let val = state.pop1(); let (br_destination, inputs) = translate_br_if_args(relative_depth, state); - let inputs = (&*inputs.0, &*inputs.1); canonicalise_then_brnz(builder, val, br_destination, inputs); let next_block = builder.create_block(); - canonicalise_then_jump(builder, next_block, (&[], &[])); + canonicalise_then_jump(builder, next_block, &[]); builder.seal_block(next_block); // The only predecessor is the current block. builder.switch_to_block(next_block); } @@ -2716,7 +2645,7 @@ fn translate_br_if( fn translate_br_if_args( relative_depth: u32, state: &mut FuncTranslationState, -) -> (ir::Block, (&mut [ir::Value], &mut [ValueExtraInfo])) { +) -> (ir::Block, &mut [ir::Value]) { let i = state.control_stack.len() - 1 - (relative_depth as usize); let (return_count, br_destination) = { let frame = &mut state.control_stack[i]; @@ -2998,10 +2927,10 @@ fn canonicalise_v128_values<'a>( fn canonicalise_then_jump( builder: &mut FunctionBuilder, destination: ir::Block, - params: (&[ir::Value], &[ValueExtraInfo]), + params: &[ir::Value], ) -> ir::Inst { let mut tmp_canonicalised = SmallVec::<[ir::Value; 16]>::new(); - let canonicalised = canonicalise_v128_values(&mut tmp_canonicalised, builder, params.0); + let canonicalised = canonicalise_v128_values(&mut tmp_canonicalised, builder, params); builder.ins().jump(destination, canonicalised) } @@ -3010,10 +2939,10 @@ fn canonicalise_then_brz( builder: &mut FunctionBuilder, cond: ir::Value, destination: ir::Block, - params: (&[ir::Value], &[ValueExtraInfo]), + params: &[ir::Value], ) -> ir::Inst { let mut tmp_canonicalised = SmallVec::<[ir::Value; 16]>::new(); - let canonicalised = canonicalise_v128_values(&mut tmp_canonicalised, builder, params.0); + let canonicalised = canonicalise_v128_values(&mut tmp_canonicalised, builder, params); builder.ins().brz(cond, destination, canonicalised) } @@ -3022,10 +2951,10 @@ fn canonicalise_then_brnz( builder: &mut FunctionBuilder, cond: ir::Value, destination: ir::Block, - params: (&[ir::Value], &[ValueExtraInfo]), + params: &[ir::Value], ) -> ir::Inst { let mut tmp_canonicalised = SmallVec::<[ir::Value; 16]>::new(); - let canonicalised = canonicalise_v128_values(&mut tmp_canonicalised, builder, params.0); + let canonicalised = canonicalise_v128_values(&mut tmp_canonicalised, builder, params); builder.ins().brnz(cond, destination, canonicalised) } @@ -3037,7 +2966,7 @@ fn pop1_with_bitcast( needed_type: Type, builder: &mut FunctionBuilder, ) -> Value { - optionally_bitcast_vector(state.pop1().0, needed_type, builder) + optionally_bitcast_vector(state.pop1(), needed_type, builder) } /// A helper for popping and bitcasting two values; since SIMD values can lose their type by @@ -3048,7 +2977,7 @@ fn pop2_with_bitcast( needed_type: Type, builder: &mut FunctionBuilder, ) -> (Value, Value) { - let ((a, _), (b, _)) = state.pop2(); + let (a, b) = state.pop2(); let bitcast_a = optionally_bitcast_vector(a, needed_type, builder); let bitcast_b = optionally_bitcast_vector(b, needed_type, builder); (bitcast_a, bitcast_b) diff --git a/lib/compiler-cranelift/src/translator/func_environ.rs b/lib/compiler-cranelift/src/translator/func_environ.rs index f5a38674210..dbd83d00217 100644 --- a/lib/compiler-cranelift/src/translator/func_environ.rs +++ b/lib/compiler-cranelift/src/translator/func_environ.rs @@ -336,20 +336,6 @@ pub trait FuncEnvironment: TargetEnvironment { len: ir::Value, ) -> WasmResult<()>; - /// Translates an externref ref count increment. - fn translate_externref_inc( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor<'_>, - externref: ir::Value, - ) -> WasmResult<()>; - - /// Translates an externref ref count decrement. - fn translate_externref_dec( - &mut self, - pos: cranelift_codegen::cursor::FuncCursor<'_>, - externref: ir::Value, - ) -> WasmResult<()>; - /// Translate a `table.init` WebAssembly instruction. #[allow(clippy::too_many_arguments)] fn translate_table_init( @@ -505,7 +491,4 @@ pub trait FuncEnvironment: TargetEnvironment { /// Get the type of a function with the given signature index. fn get_function_sig(&self, sig_index: SignatureIndex) -> Option<&FunctionType>; - - /// Drops all locals that need to be dropped. Useful for returning from functions. - fn translate_drop_locals(&mut self, builder: &mut FunctionBuilder) -> WasmResult<()>; } diff --git a/lib/compiler-cranelift/src/translator/func_state.rs b/lib/compiler-cranelift/src/translator/func_state.rs index 30da9e7c0c4..fafa6fe0d30 100644 --- a/lib/compiler-cranelift/src/translator/func_state.rs +++ b/lib/compiler-cranelift/src/translator/func_state.rs @@ -214,13 +214,6 @@ impl ControlStackFrame { } } -/// Extra info about values. For example, on the stack. -#[derive(Debug, Clone, Default)] -pub struct ValueExtraInfo { - /// Whether or not the value should be ref counted. - pub ref_counted: bool, -} - /// Contains information passed along during a function's translation and that records: /// /// - The current value and control stacks. @@ -310,63 +303,40 @@ impl FuncTranslationState { ); } - /// Push a value with extra info attached. - pub(crate) fn push1_extra(&mut self, val: (Value, ValueExtraInfo)) { - self.stack.push(val.0); - // TODO(reftypes): - //self.metadata_stack.push(val.1); - } - - /// Push a value with default extra info. + /// Push a value. pub(crate) fn push1(&mut self, val: Value) { self.stack.push(val); - // TODO(reftypes): - //self.metadata_stack.push(ValueExtraInfo::default()); } /// Push multiple values. - pub(crate) fn pushn(&mut self, vals: &[Value], _vals_metadata: &[ValueExtraInfo]) { - assert_eq!(vals.len(), _vals_metadata.len()); + pub(crate) fn pushn(&mut self, vals: &[Value]) { self.stack.extend_from_slice(vals); - // TODO(reftypes): - //self.metadata_stack.extend_from_slice(vals_metadata); } /// Pop one value. - pub(crate) fn pop1(&mut self) -> (Value, ValueExtraInfo) { - let val = self - .stack + pub(crate) fn pop1(&mut self) -> Value { + self.stack .pop() - .expect("attempted to pop a value from an empty stack"); - let val_metadata = Default::default(); - (val, val_metadata) + .expect("attempted to pop a value from an empty stack") } /// Peek at the top of the stack without popping it. - pub(crate) fn peek1(&self) -> (Value, ValueExtraInfo) { - let val = *self + pub(crate) fn peek1(&self) -> Value { + *self .stack .last() - .expect("attempted to peek at a value on an empty stack"); - let val_metadata = Default::default(); - (val, val_metadata) + .expect("attempted to peek at a value on an empty stack") } /// Pop two values. Return them in the order they were pushed. - pub(crate) fn pop2(&mut self) -> ((Value, ValueExtraInfo), (Value, ValueExtraInfo)) { + pub(crate) fn pop2(&mut self) -> (Value, Value) { let v2 = self.pop1(); let v1 = self.pop1(); (v1, v2) } /// Pop three values. Return them in the order they were pushed. - pub(crate) fn pop3( - &mut self, - ) -> ( - (Value, ValueExtraInfo), - (Value, ValueExtraInfo), - (Value, ValueExtraInfo), - ) { + pub(crate) fn pop3(&mut self) -> (Value, Value, Value) { let v3 = self.pop1(); let v2 = self.pop1(); let v1 = self.pop1(); @@ -383,13 +353,6 @@ impl FuncTranslationState { n, self.stack.len() ); - // TODO(reftypes): - /*debug_assert!( - n <= self.metadata_stack.len(), - "attempted to access {} values but stack only has {} values", - n, - self.metadata_stack.len() - );*/ } /// Pop the top `n` values on the stack. @@ -402,25 +365,16 @@ impl FuncTranslationState { } /// Peek at the top `n` values on the stack in the order they were pushed. - pub(crate) fn peekn(&self, n: usize) -> (&[Value], &[ValueExtraInfo]) { + pub(crate) fn peekn(&self, n: usize) -> &[Value] { self.ensure_length_is_at_least(n); - let vals = &self.stack[self.stack.len() - n..]; - // TODO(reftypes): - let vals_metadata = &[]; //&self.metadata_stack[self.metadata_stack.len() - n..]; - (vals, vals_metadata) + &self.stack[self.stack.len() - n..] } /// Peek at the top `n` values on the stack in the order they were pushed. - pub(crate) fn peekn_mut(&mut self, n: usize) -> (&mut [Value], &mut [ValueExtraInfo]) { + pub(crate) fn peekn_mut(&mut self, n: usize) -> &mut [Value] { self.ensure_length_is_at_least(n); let len = self.stack.len(); - // TODO(reftypes): - //let metadata_len = self.metadata_stack.len(); - //assert_eq!(len, metadata_len); - let vals = &mut self.stack[len - n..]; - // TODO(reftypes): - let vals_metadata = &mut []; //&mut self.metadata_stack[metadata_len - n..]; - (vals, vals_metadata) + &mut self.stack[len - n..] } /// Push a block on the control stack. diff --git a/lib/compiler-cranelift/src/translator/func_translator.rs b/lib/compiler-cranelift/src/translator/func_translator.rs index 13bc07da532..0f31a97a4eb 100644 --- a/lib/compiler-cranelift/src/translator/func_translator.rs +++ b/lib/compiler-cranelift/src/translator/func_translator.rs @@ -238,8 +238,6 @@ fn parse_function_body( environ.after_translate_operator(&op, builder, state)?; } - // When returning we drop all values in locals and on the stack. - // The final `End` operator left us in the exit block where we need to manually add a return // instruction. // @@ -248,23 +246,6 @@ fn parse_function_body( if state.reachable { debug_assert!(builder.is_pristine()); if !builder.is_unreachable() { - environ.translate_drop_locals(builder)?; - - let _num_elems_to_drop = state.stack.len() - builder.func.signature.returns.len(); - // drop elements on the stack that we're not returning - /*for val in state - .stack - .iter() - .zip(state.metadata_stack.iter()) - .take(num_elems_to_drop) - .filter(|(_, metadata)| metadata.ref_counted) - .map(|(val, _)| val) - { - environ.translate_externref_dec(builder.cursor(), *val)?; - }*/ - - // TODO: look into what `state.reachable` check above does as well as `!builder.is_unreachable`, do we need that too for ref counting? - match environ.return_mode() { ReturnMode::NormalReturns => { let return_types = wasm_param_types(&builder.func.signature.returns, |i| { diff --git a/lib/types/src/vmoffsets.rs b/lib/types/src/vmoffsets.rs index 3695d7ca82d..06fd6f2d25d 100644 --- a/lib/types/src/vmoffsets.rs +++ b/lib/types/src/vmoffsets.rs @@ -115,14 +115,6 @@ impl VMBuiltinFunctionIndex { pub const fn get_table_fill_index() -> Self { Self(23) } - /// Returns an index for a function to increment the externref count. - pub const fn get_externref_inc_index() -> Self { - Self(24) - } - /// Returns an index for a function to decrement the externref count. - pub const fn get_externref_dec_index() -> Self { - Self(25) - } /// Returns the total number of builtin functions. pub const fn builtin_functions_total_number() -> u32 { 26 diff --git a/lib/vm/src/libcalls.rs b/lib/vm/src/libcalls.rs index 198e311ccff..fbeb27a3c02 100644 --- a/lib/vm/src/libcalls.rs +++ b/lib/vm/src/libcalls.rs @@ -38,11 +38,11 @@ #![allow(missing_docs)] // For some reason lint fails saying that `LibCall` is not documented, when it actually is use crate::func_data_registry::VMFuncRef; +use crate::on_host_stack; use crate::probestack::PROBESTACK; use crate::table::{RawTableElement, TableElement}; use crate::trap::{raise_lib_trap, Trap, TrapCode}; use crate::vmcontext::VMContext; -use crate::{on_host_stack, VMExternRef}; pub use wasmer_types::LibCall; use wasmer_types::{ DataIndex, ElemIndex, FunctionIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, @@ -498,31 +498,6 @@ pub unsafe extern "C" fn wasmer_vm_func_ref( instance.func_ref(function_index).unwrap() } -/// Implementation of externref increment -/// -/// # Safety -/// -/// `vmctx` must be dereferenceable. -/// -/// This function must only be called at precise locations to prevent memory leaks. -#[no_mangle] -pub unsafe extern "C" fn wasmer_vm_externref_inc(externref: VMExternRef) { - externref.ref_clone(); -} - -/// Implementation of externref decrement -/// -/// # Safety -/// -/// `vmctx` must be dereferenceable. -/// -/// This function must only be called at precise locations, otherwise use-after-free -/// and other serious memory bugs may occur. -#[no_mangle] -pub unsafe extern "C" fn wasmer_vm_externref_dec(mut externref: VMExternRef) { - on_host_stack(|| externref.ref_drop()) -} - /// Implementation of `elem.drop`. /// /// # Safety diff --git a/lib/vm/src/vmcontext.rs b/lib/vm/src/vmcontext.rs index bb2257d149f..80f27a37d44 100644 --- a/lib/vm/src/vmcontext.rs +++ b/lib/vm/src/vmcontext.rs @@ -910,10 +910,6 @@ impl VMBuiltinFunctionsArray { wasmer_vm_func_ref as usize; ptrs[VMBuiltinFunctionIndex::get_table_fill_index().index() as usize] = wasmer_vm_table_fill as usize; - ptrs[VMBuiltinFunctionIndex::get_externref_inc_index().index() as usize] = - wasmer_vm_externref_inc as usize; - ptrs[VMBuiltinFunctionIndex::get_externref_dec_index().index() as usize] = - wasmer_vm_externref_dec as usize; debug_assert!(ptrs.iter().cloned().all(|p| p != 0)); From 738a66f719bf8f970ec1b5df8f09c0d32a2712cd Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 20 May 2022 12:38:28 +0100 Subject: [PATCH 02/24] Implement the new Context API for the core API Co-authored-by: ptitSeb --- lib/api/Cargo.toml | 35 +- lib/api/src/js/externals/function.rs | 27 - lib/api/src/js/imports.rs | 3 +- lib/api/src/js/module.rs | 4 +- lib/api/src/js/native.rs | 1 - lib/api/src/js/ptr.rs | 7 +- lib/api/src/sys/context.rs | 195 ++++ lib/api/src/sys/env.rs | 224 ----- lib/api/src/sys/exports.rs | 27 +- lib/api/src/sys/extern_ref.rs | 61 ++ lib/api/src/sys/externals/function.rs | 940 ++++++------------ lib/api/src/sys/externals/global.rs | 174 ++-- lib/api/src/sys/externals/memory.rs | 256 +++-- lib/api/src/sys/externals/mod.rs | 80 +- lib/api/src/sys/externals/table.rs | 184 ++-- lib/api/src/sys/imports.rs | 6 +- lib/api/src/sys/instance.rs | 95 +- lib/api/src/sys/mem_access.rs | 48 +- lib/api/src/sys/mod.rs | 44 +- lib/api/src/sys/module.rs | 21 +- lib/api/src/sys/native.rs | 246 ++--- lib/api/src/sys/native_type.rs | 236 +++++ lib/api/src/sys/ptr.rs | 48 +- lib/api/src/sys/store.rs | 6 - lib/api/src/sys/tunables.rs | 32 +- lib/api/src/sys/types.rs | 112 --- .../src/values.rs => api/src/sys/value.rs} | 300 +++--- lib/api/tests/sys_reference_types.rs | 7 - lib/c-api/src/wasm_c_api/unstable/wasi.rs | 2 +- lib/c-api/src/wasm_c_api/wasi/mod.rs | 2 +- lib/compiler/src/engine/artifact.rs | 58 +- lib/compiler/src/engine/inner.rs | 5 +- lib/compiler/src/engine/mod.rs | 2 - lib/compiler/src/engine/resolver.rs | 138 +-- lib/compiler/src/engine/tunables.rs | 45 +- lib/compiler/src/engine/universal/artifact.rs | 12 +- lib/compiler/src/engine/universal/engine.rs | 20 +- lib/derive/src/env/mod.rs | 249 ----- lib/derive/src/env/parse.rs | 143 --- lib/derive/src/lib.rs | 9 - lib/types/Cargo.toml | 3 - lib/types/src/extern_ref.rs | 294 ------ lib/types/src/indexes.rs | 12 +- lib/types/src/lib.rs | 69 +- lib/types/src/native.rs | 300 ------ lib/types/src/types.rs | 26 - lib/types/src/value.rs | 88 ++ lib/types/src/vmoffsets.rs | 16 +- lib/vm/src/context.rs | 251 +++++ lib/vm/src/export.rs | 226 +---- lib/vm/src/extern_ref.rs | 47 + lib/vm/src/func_data_registry.rs | 118 --- lib/vm/src/global.rs | 130 +-- lib/vm/src/imports.rs | 27 - lib/vm/src/instance/allocator.rs | 13 +- lib/vm/src/instance/mod.rs | 600 +++++------ lib/vm/src/instance/ref.rs | 97 -- lib/vm/src/lib.rs | 43 +- lib/vm/src/libcalls.rs | 43 +- lib/vm/src/memory.rs | 140 +-- lib/vm/src/table.rs | 321 +++--- lib/vm/src/vmcontext.rs | 301 +----- tests/lib/wast/Cargo.toml | 2 +- 63 files changed, 2583 insertions(+), 4688 deletions(-) create mode 100644 lib/api/src/sys/context.rs delete mode 100644 lib/api/src/sys/env.rs create mode 100644 lib/api/src/sys/extern_ref.rs create mode 100644 lib/api/src/sys/native_type.rs delete mode 100644 lib/api/src/sys/types.rs rename lib/{types/src/values.rs => api/src/sys/value.rs} (64%) delete mode 100644 lib/derive/src/env/mod.rs delete mode 100644 lib/derive/src/env/parse.rs delete mode 100644 lib/types/src/extern_ref.rs delete mode 100644 lib/types/src/native.rs create mode 100644 lib/types/src/value.rs create mode 100644 lib/vm/src/context.rs create mode 100644 lib/vm/src/extern_ref.rs delete mode 100644 lib/vm/src/func_data_registry.rs diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index c88d4b5a495..5883ca598fa 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -89,31 +89,13 @@ compiler = [ "sys", "wasmer-compiler/translator", ] - singlepass = [ - "compiler", - "wasmer-compiler-singlepass", - ] - cranelift = [ - "compiler", - "wasmer-compiler-cranelift", - ] - llvm = [ - "compiler", - "wasmer-compiler-llvm", - ] +singlepass = ["compiler", "wasmer-compiler-singlepass"] +cranelift = ["compiler", "wasmer-compiler-cranelift"] +llvm = ["compiler", "wasmer-compiler-llvm"] default-compiler = [] - default-singlepass = [ - "default-compiler", - "singlepass", - ] - default-cranelift = [ - "default-compiler", - "cranelift", - ] - default-llvm = [ - "default-compiler", - "llvm", - ] +default-singlepass = ["default-compiler", "singlepass"] +default-cranelift = ["default-compiler", "cranelift"] +default-llvm = ["default-compiler", "llvm"] # - Engines. engine = ["sys"] universal = [ @@ -124,11 +106,6 @@ default-universal = [ "default-engine", "universal", ] -# - Experimental / in-development features -experimental-reference-types-extern-ref = [ - "sys", - "wasmer-types/experimental-reference-types-extern-ref", -] # - Deprecated features. jit = ["universal"] diff --git a/lib/api/src/js/externals/function.rs b/lib/api/src/js/externals/function.rs index 7855b4e27b8..58981dcf150 100644 --- a/lib/api/src/js/externals/function.rs +++ b/lib/api/src/js/externals/function.rs @@ -631,19 +631,6 @@ impl fmt::Debug for Function { } } -// This is needed for reference types -impl wasmer_types::WasmValueType for Function { - /// Write the value. - unsafe fn write_value_to(&self, _p: *mut i128) { - unimplemented!(); - } - - /// Read the value. - unsafe fn read_value_from(_store: &dyn std::any::Any, _p: *const i128) -> Self { - unimplemented!(); - } -} - /// This private inner module contains the low-level implementation /// for `Function` and its siblings. mod inner { @@ -655,8 +642,6 @@ mod inner { use std::marker::PhantomData; use std::panic::{self, AssertUnwindSafe}; - #[cfg(feature = "experimental-reference-types-extern-ref")] - pub use wasmer_types::{ExternRef, VMExternRef}; use wasmer_types::{FunctionType, NativeWasmType, Type}; // use wasmer::{raise_user_trap, resume_panic}; @@ -749,18 +734,6 @@ mod inner { f64 => f64 ); - #[cfg(feature = "experimental-reference-types-extern-ref")] - unsafe impl FromToNativeWasmType for ExternRef { - type Native = VMExternRef; - - fn to_native(self) -> Self::Native { - self.into() - } - fn from_native(n: Self::Native) -> Self { - n.into() - } - } - #[cfg(test)] mod test_from_to_native_wasm_type { use super::*; diff --git a/lib/api/src/js/imports.rs b/lib/api/src/js/imports.rs index 5d7a3531112..e1543e66ea9 100644 --- a/lib/api/src/js/imports.rs +++ b/lib/api/src/js/imports.rs @@ -1,7 +1,6 @@ //! The import module contains the implementation data structures and helper functions used to //! manipulate and access a wasm module's imports including memories, tables, globals, and //! functions. -use crate::js::export::Export; use crate::js::exports::{Exportable, Exports}; use crate::js::instance::InstantiationError; use crate::js::module::Module; @@ -302,7 +301,7 @@ macro_rules! import_namespace { #[cfg(test)] mod test { - use super::*; + use crate::js::export::Export; use crate::js::exports::Exportable; use crate::js::Type; use crate::js::{Global, Store, Val}; diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index 8ed29c85148..1828ca83945 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -4,9 +4,11 @@ use crate::js::imports::Imports; use crate::js::store::Store; use crate::js::types::{ExportType, ImportType}; // use crate::js::InstantiationError; +use crate::js::error::CompileError; #[cfg(feature = "wat")] use crate::js::error::WasmError; -use crate::js::error::{CompileError, DeserializeError, SerializeError}; +#[cfg(feature = "js-serializable-module")] +use crate::js::error::{DeserializeError, SerializeError}; use crate::js::RuntimeError; use js_sys::{Reflect, Uint8Array, WebAssembly}; use std::fmt; diff --git a/lib/api/src/js/native.rs b/lib/api/src/js/native.rs index 4d56cb96c30..c99037b9fd8 100644 --- a/lib/api/src/js/native.rs +++ b/lib/api/src/js/native.rs @@ -16,7 +16,6 @@ use crate::js::types::param_from_js; use js_sys::Array; use std::iter::FromIterator; use wasm_bindgen::JsValue; -use wasmer_types::NativeWasmType; /// A WebAssembly function that can be called natively /// (using the Native ABI). diff --git a/lib/api/src/js/ptr.rs b/lib/api/src/js/ptr.rs index 32fb98da9a0..36d76481bf2 100644 --- a/lib/api/src/js/ptr.rs +++ b/lib/api/src/js/ptr.rs @@ -2,13 +2,10 @@ use crate::js::{externals::Memory, FromToNativeWasmType}; use crate::{MemoryAccessError, WasmRef, WasmSlice}; use std::convert::TryFrom; use std::{fmt, marker::PhantomData, mem}; -use wasmer_types::{NativeWasmType, ValueType}; - -pub use wasmer_types::MemorySize; - pub use wasmer_types::Memory32; - pub use wasmer_types::Memory64; +pub use wasmer_types::MemorySize; +use wasmer_types::ValueType; /// Alias for `WasmPtr. pub type WasmPtr64 = WasmPtr; diff --git a/lib/api/src/sys/context.rs b/lib/api/src/sys/context.rs new file mode 100644 index 00000000000..46ad4295420 --- /dev/null +++ b/lib/api/src/sys/context.rs @@ -0,0 +1,195 @@ +use wasmer_vm::ContextObjects; + +use crate::Store; + +/// We require the context to have a fixed memory address for its lifetime since +/// various bits of the VM have raw pointers that point back to it. Hence we +/// wrap the actual context in a box. +pub(crate) struct ContextInner { + pub(crate) objects: ContextObjects, + pub(crate) store: Store, + pub(crate) data: T, +} + +/// A context containing a set of WebAssembly instances, along with host state. +/// +/// All WebAssembly instances must exist within a context. In the majority of +/// cases each instance will have its own context, but it is possible to have +/// multiple instances in a context when these instances need to interact with +/// each other, for example sharing a memory between instances or calling +/// functions in another instance. +/// +/// The lifetimes of run-time WebAssembly objects, notably [`Instance`], +/// [`Memory`], [`Global`], [`Table`] and [`Function`] is tied to a context: +/// the backing memory for these objects is only freed when the context is +/// freed. +/// +/// The `T` generic parameter allows arbitrary data to be attached to a context. +/// This data can be accessed using the [`Context::data`] and +/// [`Context::data_mut`] methods. Host functions defined using +/// [`Function::new_with_env`] and [`Function::new_native_with_env`] receive +/// a reference to the context when they are called. +pub struct Context { + pub(crate) inner: Box>, +} + +impl Context { + /// Creates a new context with the given host state. + // TODO: Eliminate the Store type and move its functionality into Engine. + pub fn new(store: &Store, data: T) -> Self { + Self { + inner: Box::new(ContextInner { + objects: Default::default(), + store: store.clone(), + data, + }), + } + } + + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &T { + &self.inner.data + } + + /// Returns a mutable- reference to the host state in this context. + pub fn data_mut(&mut self) -> &mut T { + &mut self.inner.data + } + + /// Drops the context and returns the host state that was stored in it. + pub fn into_data(self) -> T { + self.inner.data + } + + /// Returns a reference to the `Store` of this context. + pub fn store(&self) -> &Store { + &self.inner.store + } +} + +/// A temporary handle to a [`Context`]. +pub struct ContextRef<'a, T: 'a> { + inner: &'a ContextInner, +} + +impl<'a, T> ContextRef<'a, T> { + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &'a T { + &self.inner.data + } + + /// Returns a reference to the `Store` of this context. + pub fn store(&self) -> &Store { + &self.inner.store + } + + pub(crate) fn objects(&self) -> &'a ContextObjects { + &self.inner.objects + } +} + +/// A temporary handle to a [`Context`]. +pub struct ContextMut<'a, T: 'a> { + inner: &'a mut ContextInner, +} + +impl ContextMut<'_, T> { + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &T { + &self.inner.data + } + + /// Returns a mutable- reference to the host state in this context. + pub fn data_mut(&mut self) -> &mut T { + &mut self.inner.data + } + + pub(crate) fn objects(&self) -> &ContextObjects { + &self.inner.objects + } + + pub(crate) fn objects_mut(&mut self) -> &mut ContextObjects { + &mut self.inner.objects + } + + /// Returns a reference to the `Store` of this context. + pub fn store(&self) -> &Store { + &self.inner.store + } + + pub(crate) fn as_raw(&self) -> *mut ContextInner { + self.inner as *const ContextInner as *mut ContextInner + } + + pub(crate) unsafe fn from_raw(raw: *mut ContextInner) -> Self { + Self { inner: &mut *raw } + } +} + +/// Helper trait for a value that is convertible to a [`ContextRef`]. +pub trait AsContextRef { + /// Host state associated with the [`Context`]. + type Data; + + /// Returns a `ContextRef` pointing to the underlying context. + fn as_context_ref(&self) -> ContextRef<'_, Self::Data>; +} + +/// Helper trait for a value that is convertible to a [`ContextMut`]. +pub trait AsContextMut: AsContextRef { + /// Returns a `ContextMut` pointing to the underlying context. + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data>; +} + +impl AsContextRef for Context { + type Data = T; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + ContextRef { inner: &self.inner } + } +} +impl AsContextMut for Context { + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { + ContextMut { + inner: &mut self.inner, + } + } +} +impl AsContextRef for ContextRef<'_, T> { + type Data = T; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + ContextRef { inner: self.inner } + } +} +impl AsContextRef for ContextMut<'_, T> { + type Data = T; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + ContextRef { inner: self.inner } + } +} +impl AsContextMut for ContextMut<'_, T> { + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { + ContextMut { inner: self.inner } + } +} +impl AsContextRef for &'_ T { + type Data = T::Data; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + T::as_context_ref(*self) + } +} +impl AsContextRef for &'_ mut T { + type Data = T::Data; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + T::as_context_ref(*self) + } +} +impl AsContextMut for &'_ mut T { + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { + T::as_context_mut(*self) + } +} diff --git a/lib/api/src/sys/env.rs b/lib/api/src/sys/env.rs deleted file mode 100644 index 767086d88ab..00000000000 --- a/lib/api/src/sys/env.rs +++ /dev/null @@ -1,224 +0,0 @@ -use crate::sys::{ExportError, Instance}; -use thiserror::Error; - -/// An error while initializing the user supplied host env with the `WasmerEnv` trait. -#[derive(Error, Debug)] -#[error("Host env initialization error: {0}")] -pub enum HostEnvInitError { - /// An error occurred when accessing an export - Export(ExportError), -} - -impl From for HostEnvInitError { - fn from(other: ExportError) -> Self { - Self::Export(other) - } -} - -/// Trait for initializing the environments passed to host functions after -/// instantiation but before execution. -/// -/// This is useful for filling an environment with data that can only be accesed -/// after instantiation. For example, exported items such as memories and -/// functions which don't exist prior to instantiation can be accessed here so -/// that host functions can use them. -/// -/// # Examples -/// -/// This trait can be derived like so: -/// -/// ``` -/// use wasmer::{WasmerEnv, LazyInit, Memory, TypedFunction}; -/// -/// #[derive(WasmerEnv, Clone)] -/// pub struct MyEnvWithNoInstanceData { -/// non_instance_data: u8, -/// } -/// -/// #[derive(WasmerEnv, Clone)] -/// pub struct MyEnvWithInstanceData { -/// non_instance_data: u8, -/// #[wasmer(export)] -/// memory: LazyInit, -/// #[wasmer(export(name = "real_name"))] -/// func: LazyInit>, -/// #[wasmer(export(optional = true, alias = "memory2", alias = "_memory2"))] -/// optional_memory: LazyInit, -/// } -/// -/// ``` -/// -/// When deriving `WasmerEnv`, you must wrap your types to be initialized in -/// [`LazyInit`]. The derive macro will also generate helper methods of the form -/// `_ref` and `_ref_unchecked` for easy access to the -/// data. -/// -/// The valid arguments to `export` are: -/// - `name = "string"`: specify the name of this item in the Wasm module. If this is not specified, it will default to the name of the field. -/// - `optional = true`: specify whether this export is optional. Defaults to -/// `false`. Being optional means that if the export can't be found, the -/// [`LazyInit`] will be left uninitialized. -/// - `alias = "string"`: specify additional names to look for in the Wasm module. -/// `alias` may be specified multiple times to search for multiple aliases. -/// ------- -/// -/// This trait may also be implemented manually: -/// ``` -/// # use wasmer::{WasmerEnv, LazyInit, Memory, Instance, HostEnvInitError}; -/// #[derive(Clone)] -/// pub struct MyEnv { -/// memory: LazyInit, -/// } -/// -/// impl WasmerEnv for MyEnv { -/// fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> { -/// let memory: Memory = instance.exports.get_with_generics_weak("memory").unwrap(); -/// self.memory.initialize(memory.clone()); -/// Ok(()) -/// } -/// } -/// ``` -/// -/// When implementing the trait manually, it's important to get a "weak" export to -/// prevent a cyclic reference leaking memory. You can access a "weak" export with -/// a method like `get_with_generics_weak`. -pub trait WasmerEnv: Clone + Send + Sync { - /// The function that Wasmer will call on your type to let it finish - /// setting up the environment with data from the `Instance`. - /// - /// This function is called after `Instance` is created but before it is - /// returned to the user via `Instance::new`. - fn init_with_instance(&mut self, _instance: &Instance) -> Result<(), HostEnvInitError> { - Ok(()) - } -} - -impl WasmerEnv for u8 {} -impl WasmerEnv for i8 {} -impl WasmerEnv for u16 {} -impl WasmerEnv for i16 {} -impl WasmerEnv for u32 {} -impl WasmerEnv for i32 {} -impl WasmerEnv for u64 {} -impl WasmerEnv for i64 {} -impl WasmerEnv for u128 {} -impl WasmerEnv for i128 {} -impl WasmerEnv for f32 {} -impl WasmerEnv for f64 {} -impl WasmerEnv for usize {} -impl WasmerEnv for isize {} -impl WasmerEnv for char {} -impl WasmerEnv for bool {} -impl WasmerEnv for String {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicBool {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI8 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU8 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI16 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU16 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI32 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU32 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI64 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicUsize {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicIsize {} -impl WasmerEnv for Box { - fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> { - (&mut **self).init_with_instance(instance) - } -} - -impl WasmerEnv for ::std::sync::Arc<::std::sync::Mutex> { - fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> { - let mut guard = self.lock().unwrap(); - guard.init_with_instance(instance) - } -} - -/// Lazily init an item -pub struct LazyInit { - /// The data to be initialized - data: std::mem::MaybeUninit, - /// Whether or not the data has been initialized - initialized: bool, -} - -impl LazyInit { - /// Creates an unitialized value. - pub fn new() -> Self { - Self { - data: std::mem::MaybeUninit::uninit(), - initialized: false, - } - } - - /// # Safety - /// - The data must be initialized first - pub unsafe fn get_unchecked(&self) -> &T { - &*self.data.as_ptr() - } - - /// Get the inner data. - pub fn get_ref(&self) -> Option<&T> { - if !self.initialized { - None - } else { - Some(unsafe { self.get_unchecked() }) - } - } - - /// Sets a value and marks the data as initialized. - pub fn initialize(&mut self, value: T) -> bool { - if self.initialized { - return false; - } - unsafe { - self.data.as_mut_ptr().write(value); - } - self.initialized = true; - true - } -} - -impl std::fmt::Debug for LazyInit { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("LazyInit") - .field("data", &self.get_ref()) - .finish() - } -} - -impl Clone for LazyInit { - fn clone(&self) -> Self { - if let Some(inner) = self.get_ref() { - Self { - data: std::mem::MaybeUninit::new(inner.clone()), - initialized: true, - } - } else { - Self { - data: std::mem::MaybeUninit::uninit(), - initialized: false, - } - } - } -} - -impl Drop for LazyInit { - fn drop(&mut self) { - if self.initialized { - unsafe { - let ptr = self.data.as_mut_ptr(); - std::ptr::drop_in_place(ptr); - }; - } - } -} - -impl Default for LazyInit { - fn default() -> Self { - Self::new() - } -} - -unsafe impl Send for LazyInit {} -// I thought we could opt out of sync..., look into this -// unsafe impl !Sync for InitWithInstance {} diff --git a/lib/api/src/sys/exports.rs b/lib/api/src/sys/exports.rs index a613acdfcc1..194a11104a0 100644 --- a/lib/api/src/sys/exports.rs +++ b/lib/api/src/sys/exports.rs @@ -1,3 +1,4 @@ +use super::context::AsContextRef; use crate::sys::externals::{Extern, Function, Global, Memory, Table}; use crate::sys::native::TypedFunction; use crate::sys::WasmTypeList; @@ -5,7 +6,6 @@ use indexmap::IndexMap; use std::fmt; use std::iter::{ExactSizeIterator, FromIterator}; use thiserror::Error; -use wasmer_compiler::Export; /// The `ExportError` can happen when trying to get a specific /// export [`Extern`] from the [`Instance`] exports. @@ -137,6 +137,7 @@ impl Exports { /// Get an export as a `TypedFunction`. pub fn get_native_function( &self, + ctx: impl AsContextRef, name: &str, ) -> Result, ExportError> where @@ -144,7 +145,7 @@ impl Exports { Rets: WasmTypeList, { self.get_function(name)? - .native() + .native(ctx) .map_err(|_| ExportError::IncompatibleType) } @@ -169,8 +170,7 @@ impl Exports { Rets: WasmTypeList, T: ExportableWithGenerics<'a, Args, Rets>, { - let mut out: T = self.get_with_generics(name)?; - out.convert_to_weak_instance_ref(); + let out: T = self.get_with_generics(name)?; Ok(out) } @@ -296,22 +296,11 @@ impl<'a> IntoIterator for &'a Exports { /// /// [`Instance`]: crate::Instance pub trait Exportable<'a>: Sized { - /// This function is used when providedd the [`Extern`] as exportable, so it - /// can be used while instantiating the [`Module`]. - /// - /// [`Module`]: crate::Module - fn to_export(&self) -> Export; - /// Implementation of how to get the export corresponding to the implementing type /// from an [`Instance`] by name. /// /// [`Instance`]: crate::Instance fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError>; - - /// Convert the extern internally to hold a weak reference to the `InstanceRef`. - /// This is useful for preventing cycles, for example for data stored in a - /// type implementing `WasmerEnv`. - fn convert_to_weak_instance_ref(&mut self); } /// A trait for accessing exports (like [`Exportable`]) but it takes generic @@ -320,10 +309,6 @@ pub trait Exportable<'a>: Sized { pub trait ExportableWithGenerics<'a, Args: WasmTypeList, Rets: WasmTypeList>: Sized { /// Get an export with the given generics. fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result; - /// Convert the extern internally to hold a weak reference to the `InstanceRef`. - /// This is useful for preventing cycles, for example for data stored in a - /// type implementing `WasmerEnv`. - fn convert_to_weak_instance_ref(&mut self); } /// We implement it for all concrete [`Exportable`] types (that are `Clone`) @@ -332,8 +317,4 @@ impl<'a, T: Exportable<'a> + Clone + 'static> ExportableWithGenerics<'a, (), ()> fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result { T::get_self_from_extern(_extern).map(|i| i.clone()) } - - fn convert_to_weak_instance_ref(&mut self) { - ::convert_to_weak_instance_ref(self); - } } diff --git a/lib/api/src/sys/extern_ref.rs b/lib/api/src/sys/extern_ref.rs new file mode 100644 index 00000000000..395a336dd70 --- /dev/null +++ b/lib/api/src/sys/extern_ref.rs @@ -0,0 +1,61 @@ +use std::any::Any; + +use wasmer_vm::{ContextHandle, VMExternObj, VMExternRef}; + +use crate::ContextRef; + +use super::context::{AsContextMut, AsContextRef}; + +#[derive(Debug, Clone)] +#[repr(transparent)] +/// An opaque reference to some data. This reference can be passed through Wasm. +pub struct ExternRef { + handle: ContextHandle, +} + +impl ExternRef { + /// Make a new extern reference + pub fn new(mut ctx: impl AsContextMut, value: T) -> Self + where + T: Any + Send + Sync + 'static + Sized, + { + Self { + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), VMExternObj::new(value)), + } + } + + /// Try to downcast to the given value. + pub fn downcast<'a, T, U>(&self, ctx: ContextRef<'a, U>) -> Option<&'a T> + where + T: Any + Send + Sync + 'static + Sized, + { + self.handle.get(ctx.objects()).as_ref().downcast_ref::() + } + + pub(crate) fn vm_externref(&self) -> VMExternRef { + VMExternRef(self.handle.internal_handle()) + } + + pub(crate) unsafe fn from_vm_externref( + mut ctx: impl AsContextMut, + vm_externref: VMExternRef, + ) -> Self { + Self { + handle: ContextHandle::from_internal( + ctx.as_context_mut().objects_mut().id(), + vm_externref.0, + ), + } + } + + /// Checks whether this `ExternRef` can be used with the given context. + /// + /// Primitive (`i32`, `i64`, etc) and null funcref/externref values are not + /// tied to a context and can be freely shared between contexts. + /// + /// Externref and funcref values are tied to a context and can only be used + /// with that context. + pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() + } +} diff --git a/lib/api/src/sys/externals/function.rs b/lib/api/src/sys/externals/function.rs index 5f8b1eae14c..54fe895252c 100644 --- a/lib/api/src/sys/externals/function.rs +++ b/lib/api/src/sys/externals/function.rs @@ -1,21 +1,21 @@ +use crate::sys::context::{AsContextMut, AsContextRef, ContextInner, ContextMut}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; -use crate::sys::store::Store; -use crate::sys::types::{Val, ValFuncRef}; use crate::sys::FunctionType; use crate::sys::RuntimeError; use crate::sys::TypedFunction; -use crate::sys::WasmerEnv; -pub use inner::{FromToNativeWasmType, HostFunction, WasmTypeList, WithEnv, WithoutEnv}; +use crate::Value; +use inner::StaticFunction; +pub use inner::{FromToNativeWasmType, HostFunction, WasmTypeList}; +use std::cell::UnsafeCell; use std::cmp::max; use std::ffi::c_void; -use std::fmt; -use std::sync::Arc; -use wasmer_compiler::{Export, ExportFunction, ExportFunctionMetadata}; +use wasmer_types::RawValue; use wasmer_vm::{ - on_host_stack, raise_user_trap, resume_panic, wasmer_call_trampoline, ImportInitializerFuncPtr, - VMCallerCheckedAnyfunc, VMDynamicFunctionContext, VMFuncRef, VMFunction, VMFunctionBody, + on_host_stack, raise_user_trap, resume_panic, wasmer_call_trampoline, ContextHandle, + InternalContextHandle, MaybeInstanceOwned, VMCallerCheckedAnyfunc, VMContext, + VMDynamicFunctionContext, VMExtern, VMFuncRef, VMFunction, VMFunctionBody, VMFunctionEnvironment, VMFunctionKind, VMTrampoline, }; @@ -36,78 +36,11 @@ use wasmer_vm::{ /// with native functions. Attempting to create a native `Function` with one will /// result in a panic. /// [Closures as host functions tracking issue](https://github.com/wasmerio/wasmer/issues/1840) -#[derive(PartialEq)] +#[derive(Debug, Clone)] pub struct Function { - pub(crate) store: Store, - pub(crate) exported: ExportFunction, + pub(crate) handle: ContextHandle, } -impl wasmer_types::WasmValueType for Function { - /// Write the value. - unsafe fn write_value_to(&self, p: *mut i128) { - let func_ref = Val::into_vm_funcref(Val::FuncRef(Some(self.clone())), &self.store).unwrap(); - std::ptr::write(p as *mut VMFuncRef, func_ref); - } - - /// Read the value. - // TODO(reftypes): this entire function should be cleaned up, `dyn Any` should - // ideally be removed - unsafe fn read_value_from(store: &dyn std::any::Any, p: *const i128) -> Self { - let func_ref = std::ptr::read(p as *const VMFuncRef); - let store = store.downcast_ref::().expect("Store expected in `Function::read_value_from`. If you see this error message it likely means you're using a function ref in a place we don't yet support it -- sorry about the inconvenience."); - match Val::from_vm_funcref(func_ref, store) { - Val::FuncRef(Some(fr)) => fr, - // these bottom two cases indicate bugs in `wasmer-types` or elsewhere. - // They should never be triggered, so we just panic. - Val::FuncRef(None) => panic!("Null funcref found in `Function::read_value_from`!"), - other => panic!("Invalid value in `Function::read_value_from`: {:?}", other), - } - } -} - -fn build_export_function_metadata( - env: Env, - import_init_function_ptr: for<'a> fn( - &'a mut Env, - &'a crate::Instance, - ) -> Result<(), crate::HostEnvInitError>, -) -> (*mut c_void, ExportFunctionMetadata) -where - Env: Clone + Sized + 'static + Send + Sync, -{ - let import_init_function_ptr = Some(unsafe { - std::mem::transmute::<_, ImportInitializerFuncPtr>(import_init_function_ptr) - }); - let host_env_clone_fn = |ptr: *mut c_void| -> *mut c_void { - let env_ref: &Env = unsafe { - ptr.cast::() - .as_ref() - .expect("`ptr` to the environment is null when cloning it") - }; - Box::into_raw(Box::new(env_ref.clone())) as _ - }; - let host_env_drop_fn = |ptr: *mut c_void| { - unsafe { Box::from_raw(ptr.cast::()) }; - }; - let env = Box::into_raw(Box::new(env)) as _; - - // # Safety - // - All these functions work on all threads - // - The host env is `Send`. - let metadata = unsafe { - ExportFunctionMetadata::new( - env, - import_init_function_ptr, - host_env_clone_fn, - host_env_drop_fn, - ) - }; - - (env, metadata) -} - -impl WasmerEnv for WithoutEnv {} - impl Function { /// Creates a new host `Function` (dynamic) with the provided signature. /// @@ -141,106 +74,77 @@ impl Function { /// Ok(vec![Value::I32(sum)]) /// }); /// ``` - #[allow(clippy::cast_ptr_alignment)] - pub fn new(store: &Store, ty: FT, func: F) -> Self + pub fn new(mut ctx: impl AsContextMut, ty: FT, func: F) -> Self where FT: Into, - F: Fn(&[Val]) -> Result, RuntimeError> + 'static + Send + Sync, + F: Fn(ContextMut<'_, T>, &[Value]) -> Result, RuntimeError> + + 'static + + Send + + Sync, { - let wrapped_func = - move |_env: &WithoutEnv, args: &[Val]| -> Result, RuntimeError> { func(args) }; - Self::new_with_env(store, ty, WithoutEnv, wrapped_func) - } + let mut ctx = ctx.as_context_mut(); + let function_type = ty.into(); + let func_ty = function_type.clone(); + let raw_ctx = ctx.as_raw() as *mut u8; + let wrapper = move |values_vec: *mut RawValue| -> Result<(), RuntimeError> { + unsafe { + let mut ctx = ContextMut::from_raw(raw_ctx as *mut ContextInner); + let mut args = Vec::with_capacity(func_ty.params().len()); + for (i, ty) in func_ty.params().iter().enumerate() { + args.push(Value::from_raw( + ctx.as_context_mut(), + *ty, + *values_vec.add(i), + )); + } + let returns = func(ctx.as_context_mut(), &args)?; - /// Creates a new host `Function` (dynamic) with the provided signature and environment. - /// - /// If you know the signature of the host function at compile time, - /// consider using [`Function::new_native_with_env`] for less runtime - /// overhead. - /// - /// # Examples - /// - /// ``` - /// # use wasmer::{Function, FunctionType, Type, Store, Value, WasmerEnv}; - /// # let store = Store::default(); - /// # - /// #[derive(WasmerEnv, Clone)] - /// struct Env { - /// multiplier: i32, - /// }; - /// let env = Env { multiplier: 2 }; - /// - /// let signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]); - /// - /// let f = Function::new_with_env(&store, &signature, env, |env, args| { - /// let result = env.multiplier * (args[0].unwrap_i32() + args[1].unwrap_i32()); - /// Ok(vec![Value::I32(result)]) - /// }); - /// ``` - /// - /// With constant signature: - /// - /// ``` - /// # use wasmer::{Function, FunctionType, Type, Store, Value, WasmerEnv}; - /// # let store = Store::default(); - /// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]); - /// - /// #[derive(WasmerEnv, Clone)] - /// struct Env { - /// multiplier: i32, - /// }; - /// let env = Env { multiplier: 2 }; - /// - /// let f = Function::new_with_env(&store, I32_I32_TO_I32, env, |env, args| { - /// let result = env.multiplier * (args[0].unwrap_i32() + args[1].unwrap_i32()); - /// Ok(vec![Value::I32(result)]) - /// }); - /// ``` - #[allow(clippy::cast_ptr_alignment)] - pub fn new_with_env(store: &Store, ty: FT, env: Env, func: F) -> Self - where - FT: Into, - F: Fn(&Env, &[Val]) -> Result, RuntimeError> + 'static + Send + Sync, - Env: Sized + WasmerEnv + 'static, - { - let ty: FunctionType = ty.into(); - let dynamic_ctx: VMDynamicFunctionContext> = - VMDynamicFunctionContext::from_context(DynamicFunction { - env: Box::new(env), - func: Arc::new(func), - store: store.clone(), - function_type: ty.clone(), - }); - - let import_init_function_ptr: for<'a> fn(&'a mut _, &'a _) -> Result<(), _> = - |env: &mut VMDynamicFunctionContext>, - instance: &crate::Instance| { - Env::init_with_instance(&mut *env.ctx.env, instance) - }; - - let (host_env, metadata) = build_export_function_metadata::< - VMDynamicFunctionContext>, - >(dynamic_ctx, import_init_function_ptr); + // We need to dynamically check that the returns + // match the expected types, as well as expected length. + let return_types = returns.iter().map(|ret| ret.ty()); + if return_types.ne(func_ty.results().iter().copied()) { + return Err(RuntimeError::new(format!( + "Dynamic function returned wrong signature. Expected {:?} but got {:?}", + func_ty.results(), + returns.iter().map(|ret| ret.ty()) + ))); + } + for (i, ret) in returns.iter().enumerate() { + *values_vec.add(i) = ret.as_raw(ctx.as_context_mut()); + } + } + Ok(()) + }; + let mut host_data = Box::new(VMDynamicFunctionContext { + address: std::ptr::null(), + ctx: DynamicFunction { func: wrapper }, + }); + host_data.address = host_data.ctx.func_body_ptr(); // We don't yet have the address with the Wasm ABI signature. // The engine linker will replace the address with one pointing to a // generated dynamic trampoline. - let address = std::ptr::null() as *const VMFunctionBody; - let vmctx = VMFunctionEnvironment { host_env }; + let func_ptr = std::ptr::null() as *const VMFunctionBody; + let type_index = ctx.store().engine().register_signature(&function_type); + let vmctx = VMFunctionEnvironment { + host_env: host_data.as_ref() as *const _ as *mut c_void, + }; + let call_trampoline = host_data.ctx.call_trampoline_address(); + let anyfunc = VMCallerCheckedAnyfunc { + func_ptr, + type_index, + vmctx, + call_trampoline, + }; + let vm_function = VMFunction { + anyfunc: MaybeInstanceOwned::Host(Box::new(UnsafeCell::new(anyfunc))), + kind: VMFunctionKind::Dynamic, + signature: function_type, + host_data, + }; Self { - store: store.clone(), - exported: ExportFunction { - metadata: Some(Arc::new(metadata)), - vm_function: VMFunction { - address, - kind: VMFunctionKind::Dynamic, - vmctx, - signature: ty, - call_trampoline: None, - instance_ref: None, - }, - }, + handle: ContextHandle::new(ctx.objects_mut(), vm_function), } } @@ -261,96 +165,40 @@ impl Function { /// /// let f = Function::new_native(&store, sum); /// ``` - pub fn new_native(store: &Store, func: F) -> Self + pub fn new_native(mut ctx: impl AsContextMut, func: F) -> Self where - F: HostFunction, + F: HostFunction + 'static + Send + Sync, Args: WasmTypeList, Rets: WasmTypeList, - Env: Sized + 'static, { - if std::mem::size_of::() != 0 { - Self::closures_unsupported_panic(); - } - let function = inner::Function::::new(func); - let address = function.address() as *const VMFunctionBody; + let mut ctx = ctx.as_context_mut(); + let host_data = Box::new(StaticFunction { + raw_ctx: ctx.as_raw() as *mut u8, + func, + }); + let function_type = FunctionType::new(Args::wasm_types(), Rets::wasm_types()); + + let func_ptr = >::function_body_ptr(); + let type_index = ctx.store().engine().register_signature(&function_type); let vmctx = VMFunctionEnvironment { - host_env: std::ptr::null_mut() as *mut _, + host_env: host_data.as_ref() as *const _ as *mut c_void, + }; + let call_trampoline = >::call_trampoline_address(); + let anyfunc = VMCallerCheckedAnyfunc { + func_ptr, + type_index, + vmctx, + call_trampoline, }; - let signature = function.ty(); - - Self { - store: store.clone(), - exported: ExportFunction { - // TODO: figure out what's going on in this function: it takes an `Env` - // param but also marks itself as not having an env - metadata: None, - vm_function: VMFunction { - address, - vmctx, - signature, - kind: VMFunctionKind::Static, - call_trampoline: None, - instance_ref: None, - }, - }, - } - } - - /// Creates a new host `Function` from a native function and a provided environment. - /// - /// The function signature is automatically retrieved using the - /// Rust typing system. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Store, Function, WasmerEnv}; - /// # let store = Store::default(); - /// # - /// #[derive(WasmerEnv, Clone)] - /// struct Env { - /// multiplier: i32, - /// }; - /// let env = Env { multiplier: 2 }; - /// - /// fn sum_and_multiply(env: &Env, a: i32, b: i32) -> i32 { - /// (a + b) * env.multiplier - /// } - /// - /// let f = Function::new_native_with_env(&store, env, sum_and_multiply); - /// ``` - pub fn new_native_with_env(store: &Store, env: Env, func: F) -> Self - where - F: HostFunction, - Args: WasmTypeList, - Rets: WasmTypeList, - Env: Sized + WasmerEnv + 'static, - { - if std::mem::size_of::() != 0 { - Self::closures_unsupported_panic(); - } - let function = inner::Function::::new(func); - let address = function.address(); - - let (host_env, metadata) = - build_export_function_metadata::(env, Env::init_with_instance); - - let vmctx = VMFunctionEnvironment { host_env }; - let signature = function.ty(); + let vm_function = VMFunction { + anyfunc: MaybeInstanceOwned::Host(Box::new(UnsafeCell::new(anyfunc))), + kind: VMFunctionKind::Static, + signature: function_type, + host_data, + }; Self { - store: store.clone(), - exported: ExportFunction { - metadata: Some(Arc::new(metadata)), - vm_function: VMFunction { - address, - kind: VMFunctionKind::Static, - vmctx, - signature, - call_trampoline: None, - instance_ref: None, - }, - }, + handle: ContextHandle::new(ctx.objects_mut(), vm_function), } } @@ -371,29 +219,29 @@ impl Function { /// assert_eq!(f.ty().params(), vec![Type::I32, Type::I32]); /// assert_eq!(f.ty().results(), vec![Type::I32]); /// ``` - pub fn ty(&self) -> &FunctionType { - &self.exported.vm_function.signature - } - - /// Returns the [`Store`] where the `Function` belongs. - pub fn store(&self) -> &Store { - &self.store + pub fn ty(&self, ctx: impl AsContextRef) -> FunctionType { + self.handle + .get(ctx.as_context_ref().objects()) + .signature + .clone() } fn call_wasm( &self, + mut ctx: impl AsContextMut, trampoline: VMTrampoline, - params: &[Val], - results: &mut [Val], + params: &[Value], + results: &mut [Value], ) -> Result<(), RuntimeError> { - let format_types_for_error_message = |items: &[Val]| { + let format_types_for_error_message = |items: &[Value]| { items .iter() .map(|param| param.ty().to_string()) .collect::>() .join(", ") }; - let signature = self.ty(); + // TODO: Avoid cloning the signature here, it's expensive. + let signature = self.ty(ctx.as_context_ref()); if signature.params().len() != params.len() { return Err(RuntimeError::new(format!( "Parameters of type [{}] did not match signature {}", @@ -409,7 +257,7 @@ impl Function { ))); } - let mut values_vec = vec![0; max(params.len(), results.len())]; + let mut values_vec = vec![RawValue { i32: 0 }; max(params.len(), results.len())]; // Store the argument values into `values_vec`. let param_tys = signature.params().iter(); @@ -421,18 +269,17 @@ impl Function { param_types, &signature, ))); } - unsafe { - arg.write_value_to(slot); - } + *slot = arg.as_raw(ctx.as_context_mut()); } // Call the trampoline. + let vm_function = self.handle.get(ctx.as_context_ref().objects()); if let Err(error) = unsafe { wasmer_call_trampoline( - &self.store, - self.exported.vm_function.vmctx, + ctx.as_context_ref().store(), + vm_function.anyfunc.as_ptr().as_ref().vmctx, trampoline, - self.exported.vm_function.address, + vm_function.anyfunc.as_ptr().as_ref().func_ptr, values_vec.as_mut_ptr() as *mut u8, ) } { @@ -442,8 +289,8 @@ impl Function { // Load the return values out of `values_vec`. for (index, &value_type) in signature.results().iter().enumerate() { unsafe { - let ptr = values_vec.as_ptr().add(index); - results[index] = Val::read_value_from(&self.store, ptr, value_type); + results[index] = + Value::from_raw(ctx.as_context_mut(), value_type, values_vec[index]); } } @@ -466,8 +313,8 @@ impl Function { /// /// assert_eq!(f.param_arity(), 2); /// ``` - pub fn param_arity(&self) -> usize { - self.ty().params().len() + pub fn param_arity(&self, ctx: impl AsContextRef) -> usize { + self.ty(ctx).params().len() } /// Returns the number of results this function produces. @@ -486,8 +333,8 @@ impl Function { /// /// assert_eq!(f.result_arity(), 1); /// ``` - pub fn result_arity(&self) -> usize { - self.ty().results().len() + pub fn result_arity(&self, ctx: impl AsContextRef) -> usize { + self.ty(ctx).results().len() } /// Call the `Function` function. @@ -519,46 +366,52 @@ impl Function { /// /// assert_eq!(sum.call(&[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); /// ``` - pub fn call(&self, params: &[Val]) -> Result, RuntimeError> { - // If it's a function defined in the Wasm, it will always have a call_trampoline - if let Some(trampoline) = self.exported.vm_function.call_trampoline { - let mut results = vec![Val::null(); self.result_arity()]; - self.call_wasm(trampoline, params, &mut results)?; - return Ok(results.into_boxed_slice()); - } + pub fn call( + &self, + mut ctx: impl AsContextMut, + params: &[Value], + ) -> Result, RuntimeError> { + let trampoline = unsafe { + self.handle + .get(ctx.as_context_ref().objects()) + .anyfunc + .as_ptr() + .as_ref() + .call_trampoline + }; + let mut results = vec![Value::null(); self.result_arity(ctx.as_context_ref())]; + self.call_wasm(ctx.as_context_mut(), trampoline, params, &mut results)?; + Ok(results.into_boxed_slice()) + } - // If it's a function defined in the host - match self.exported.vm_function.kind { - VMFunctionKind::Dynamic => unsafe { - type VMContextWithEnv = VMDynamicFunctionContext>; - let ctx = self.exported.vm_function.vmctx.host_env as *mut VMContextWithEnv; - Ok((*ctx).ctx.call(params)?.into_boxed_slice()) - }, - VMFunctionKind::Static => { - unimplemented!( - "Native function definitions can't be directly called from the host yet" - ); - } + pub(crate) fn vm_funcref(&self, ctx: impl AsContextRef) -> VMFuncRef { + let vm_function = self.handle.get(ctx.as_context_ref().objects()); + if vm_function.kind == VMFunctionKind::Dynamic { + panic!("dynamic functions cannot be used in tables or as funcrefs"); } + VMFuncRef(vm_function.anyfunc.as_ptr()) } - pub(crate) fn from_vm_export(store: &Store, wasmer_export: ExportFunction) -> Self { + pub(crate) unsafe fn from_vm_funcref(mut ctx: impl AsContextMut, funcref: VMFuncRef) -> Self { + let signature = ctx + .as_context_mut() + .store() + .engine() + .lookup_signature(funcref.0.as_ref().type_index) + .expect("Signature not found in store"); + let vm_function = VMFunction { + anyfunc: MaybeInstanceOwned::Instance(funcref.0), + signature, + // All functions in tables are already Static (as dynamic functions + // are converted to use the trampolines with static signatures). + kind: wasmer_vm::VMFunctionKind::Static, + host_data: Box::new(()), + }; Self { - store: store.clone(), - exported: wasmer_export, + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), } } - pub(crate) fn vm_funcref(&self) -> VMFuncRef { - let engine = self.store.engine(); - let vmsignature = engine.register_signature(&self.exported.vm_function.signature); - engine.register_function_metadata(VMCallerCheckedAnyfunc { - func_ptr: self.exported.vm_function.address, - type_index: vmsignature, - vmctx: self.exported.vm_function.vmctx, - }) - } - /// Transform this WebAssembly function into a function with the /// native ABI. See [`TypedFunction`] to learn more. /// @@ -634,14 +487,19 @@ impl Function { /// // This results in an error: `RuntimeError` /// let sum_native = sum.native::<(i32, i32), i64>().unwrap(); /// ``` - pub fn native(&self) -> Result, RuntimeError> + pub fn native( + &self, + ctx: impl AsContextRef, + ) -> Result, RuntimeError> where Args: WasmTypeList, Rets: WasmTypeList, { + let vm_function = self.handle.get(ctx.as_context_ref().objects()); + // type check { - let expected = self.exported.vm_function.signature.params(); + let expected = vm_function.signature.params(); let given = Args::wasm_types(); if expected != given { @@ -654,7 +512,7 @@ impl Function { } { - let expected = self.exported.vm_function.signature.results(); + let expected = vm_function.signature.results(); let given = Rets::wasm_types(); if expected != given { @@ -667,169 +525,57 @@ impl Function { } } - Ok(TypedFunction::new( - self.store.clone(), - self.exported.clone(), - )) + Ok(TypedFunction::new(self.clone())) } - #[track_caller] - fn closures_unsupported_panic() -> ! { - unimplemented!("Closures (functions with captured environments) are currently unsupported with native functions. See: https://github.com/wasmerio/wasmer/issues/1840") + pub(crate) fn from_vm_extern( + ctx: impl AsContextMut, + internal: InternalContextHandle, + ) -> Self { + Self { + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, + } } - /// Get access to the backing VM value for this extern. This function is for - /// tests it should not be called by users of the Wasmer API. - /// - /// # Safety - /// This function is unsafe to call outside of tests for the wasmer crate - /// because there is no stability guarantee for the returned type and we may - /// make breaking changes to it at any time or remove this method. - #[doc(hidden)] - pub unsafe fn get_vm_function(&self) -> &VMFunction { - &self.exported.vm_function + /// Checks whether this `Function` can be used with the given context. + pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } -} -impl<'a> Exportable<'a> for Function { - fn to_export(&self) -> Export { - self.exported.clone().into() + pub(crate) fn to_vm_extern(&self) -> VMExtern { + VMExtern::Function(self.handle.internal_handle()) } +} +impl<'a> Exportable<'a> for Function { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Function(func) => Ok(func), _ => Err(ExportError::IncompatibleType), } } - - fn convert_to_weak_instance_ref(&mut self) { - if let Some(v) = self.exported.vm_function.instance_ref.as_mut() { - *v = v.downgrade(); - } - } -} - -impl Clone for Function { - fn clone(&self) -> Self { - let mut exported = self.exported.clone(); - exported.vm_function.upgrade_instance_ref().unwrap(); - - Self { - store: self.store.clone(), - exported, - } - } -} - -impl fmt::Debug for Function { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter - .debug_struct("Function") - .field("ty", &self.ty()) - .finish() - } -} - -/// This trait is one that all dynamic functions must fulfill. -pub(crate) trait VMDynamicFunction: Send + Sync { - fn call(&self, args: &[Val]) -> Result, RuntimeError>; - fn function_type(&self) -> &FunctionType; - fn store(&self) -> &Store; } -pub(crate) struct DynamicFunction -where - Env: Sized + 'static + Send + Sync, -{ - function_type: FunctionType, - #[allow(clippy::type_complexity)] - func: Arc Result, RuntimeError> + 'static + Send + Sync>, - store: Store, - env: Box, -} - -impl Clone for DynamicFunction { - fn clone(&self) -> Self { - Self { - env: self.env.clone(), - function_type: self.function_type.clone(), - store: self.store.clone(), - func: self.func.clone(), - } - } +/// Host state for a dynamic function. +pub(crate) struct DynamicFunction { + func: F, } -impl VMDynamicFunction for DynamicFunction +impl DynamicFunction where - Env: Sized + 'static + Send + Sync, + F: Fn(*mut RawValue) -> Result<(), RuntimeError> + 'static, { - fn call(&self, args: &[Val]) -> Result, RuntimeError> { - (*self.func)(&*self.env, args) - } - fn function_type(&self) -> &FunctionType { - &self.function_type - } - fn store(&self) -> &Store { - &self.store - } -} - -trait VMDynamicFunctionCall { - fn from_context(ctx: T) -> Self; - fn address_ptr() -> *const VMFunctionBody; - unsafe fn func_wrapper(&self, values_vec: *mut i128); -} - -impl VMDynamicFunctionCall for VMDynamicFunctionContext { - fn from_context(ctx: T) -> Self { - Self { - address: Self::address_ptr(), - ctx, - } - } - - fn address_ptr() -> *const VMFunctionBody { - Self::func_wrapper as *const () as *const VMFunctionBody - } - // This function wraps our func, to make it compatible with the // reverse trampoline signature - unsafe fn func_wrapper( - // Note: we use the trick that the first param to this function is the `VMDynamicFunctionContext` - // itself, so rather than doing `dynamic_ctx: &VMDynamicFunctionContext`, we simplify it a bit - &self, - values_vec: *mut i128, + unsafe extern "C" fn func_wrapper( + this: &VMDynamicFunctionContext, + values_vec: *mut RawValue, ) { use std::panic::{self, AssertUnwindSafe}; - let result = on_host_stack(|| { - panic::catch_unwind(AssertUnwindSafe(|| { - let func_ty = self.ctx.function_type(); - let mut args = Vec::with_capacity(func_ty.params().len()); - let store = self.ctx.store(); - for (i, ty) in func_ty.params().iter().enumerate() { - args.push(Val::read_value_from(store, values_vec.add(i), *ty)); - } - let returns = self.ctx.call(&args)?; - - // We need to dynamically check that the returns - // match the expected types, as well as expected length. - let return_types = returns.iter().map(|ret| ret.ty()).collect::>(); - if return_types != func_ty.results() { - return Err(RuntimeError::new(format!( - "Dynamic function returned wrong signature. Expected {:?} but got {:?}", - func_ty.results(), - return_types - ))); - } - for (i, ret) in returns.iter().enumerate() { - ret.write_value_to(values_vec.add(i)); - } - Ok(()) - })) // We get extern ref drops at the end of this block that we don't need. - // By preventing extern ref incs in the code above we can save the work of - // incrementing and decrementing. However the logic as-is is correct. - }); + let result = + on_host_stack(|| panic::catch_unwind(AssertUnwindSafe(|| (this.ctx.func)(values_vec)))); match result { Ok(Ok(())) => {} @@ -837,6 +583,25 @@ impl VMDynamicFunctionCall for VMDynamicFunctionContext Err(panic) => resume_panic(panic), } } + + fn func_body_ptr(&self) -> *const VMFunctionBody { + Self::func_wrapper as *const VMFunctionBody + } + + fn call_trampoline_address(&self) -> VMTrampoline { + Self::call_trampoline + } + + unsafe extern "C" fn call_trampoline( + vmctx: *mut VMContext, + _body: *const VMFunctionBody, + args: *mut RawValue, + ) { + // The VMFunctionBody pointer is null here: it is only filled in later + // by the engine linker. + let dynamic_function = &mut *(vmctx as *mut VMDynamicFunctionContext); + Self::func_wrapper(dynamic_function, args); + } } /// This private inner module contains the low-level implementation @@ -845,15 +610,16 @@ mod inner { use std::array::TryFromSliceError; use std::convert::{Infallible, TryInto}; use std::error::Error; - use std::marker::PhantomData; use std::panic::{self, AssertUnwindSafe}; - use wasmer_vm::on_host_stack; + use wasmer_vm::{on_host_stack, VMTrampoline}; - #[cfg(feature = "experimental-reference-types-extern-ref")] - pub use wasmer_types::{ExternRef, VMExternRef}; - use wasmer_types::{FunctionType, NativeWasmType, Type}; + use wasmer_types::{NativeWasmType, RawValue, Type}; use wasmer_vm::{raise_user_trap, resume_panic, VMFunctionBody}; + use crate::sys::context::{ContextInner, ContextMut}; + use crate::sys::NativeWasmTypeInto; + use crate::{AsContextMut, ExternRef, Function}; + /// A trait to convert a Rust value to a `WasmNativeType` value, /// or to convert `WasmNativeType` value to a Rust value. /// @@ -870,7 +636,7 @@ mod inner { Self: Sized, { /// Native Wasm type. - type Native: NativeWasmType; + type Native: NativeWasmTypeInto; /// Convert a value of kind `Self::Native` to `Self`. /// @@ -947,15 +713,25 @@ mod inner { f64 => f64 ); - #[cfg(feature = "experimental-reference-types-extern-ref")] - unsafe impl FromToNativeWasmType for ExternRef { - type Native = VMExternRef; + unsafe impl FromToNativeWasmType for Option { + type Native = Self; fn to_native(self) -> Self::Native { - self.into() + self } fn from_native(n: Self::Native) -> Self { - n.into() + n + } + } + + unsafe impl FromToNativeWasmType for Option { + type Native = Self; + + fn to_native(self) -> Self::Native { + self + } + fn from_native(n: Self::Native) -> Self { + n } } @@ -997,10 +773,12 @@ mod inner { /// The array type that can hold all the represented values. /// /// Note that all values are stored in their binary form. - type Array: AsMut<[i128]>; + type Array: AsMut<[RawValue]>; /// Constructs `Self` based on an array of values. - fn from_array(array: Self::Array) -> Self; + /// + /// # Safety + unsafe fn from_array(ctx: impl AsContextMut, array: Self::Array) -> Self; /// Constructs `Self` based on a slice of values. /// @@ -1008,11 +786,18 @@ mod inner { /// that the slice doesn't have the same size than /// `Self::Array`, in which circumstance an error of kind /// `TryFromSliceError` will be returned. - fn from_slice(slice: &[i128]) -> Result; + /// + /// # Safety + unsafe fn from_slice( + ctx: impl AsContextMut, + slice: &[RawValue], + ) -> Result; /// Builds and returns an array of type `Array` from a tuple /// (list) of values. - fn into_array(self) -> Self::Array; + /// + /// # Safety + unsafe fn into_array(self, ctx: impl AsContextMut) -> Self::Array; /// Allocates and return an empty array of type `Array` that /// will hold a tuple (list) of values, usually to hold the @@ -1021,11 +806,15 @@ mod inner { /// Builds a tuple (list) of values from a C struct of type /// `CStruct`. - fn from_c_struct(c_struct: Self::CStruct) -> Self; + /// + /// # Safety + unsafe fn from_c_struct(ctx: impl AsContextMut, c_struct: Self::CStruct) -> Self; /// Builds and returns a C struct of type `CStruct` from a /// tuple (list) of values. - fn into_c_struct(self) -> Self::CStruct; + /// + /// # Safety + unsafe fn into_c_struct(self, ctx: impl AsContextMut) -> Self::CStruct; /// Get the Wasm types for the tuple (list) of currently /// represented values. @@ -1121,78 +910,23 @@ mod inner { /// can be used as host function. To uphold this statement, it is /// necessary for a function to be transformed into a pointer to /// `VMFunctionBody`. - pub trait HostFunction + pub trait HostFunction where Args: WasmTypeList, Rets: WasmTypeList, - Kind: HostFunctionKind, - T: Sized, - Self: Sized, { /// Get the pointer to the function body. - fn function_body_ptr(self) -> *const VMFunctionBody; - } - - /// Empty trait to specify the kind of `HostFunction`: With or - /// without an environment. - /// - /// This trait is never aimed to be used by a user. It is used by - /// the trait system to automatically generate the appropriate - /// host functions. - #[doc(hidden)] - pub trait HostFunctionKind {} - - /// An empty struct to help Rust typing to determine - /// when a `HostFunction` does have an environment. - pub struct WithEnv; + fn function_body_ptr() -> *const VMFunctionBody; - impl HostFunctionKind for WithEnv {} - - /// An empty struct to help Rust typing to determine - /// when a `HostFunction` does not have an environment. - #[derive(Clone)] - pub struct WithoutEnv; - - impl HostFunctionKind for WithoutEnv {} - - /// Represents a low-level Wasm static host function. See - /// `super::Function::new` and `super::Function::new_env` to learn - /// more. - #[derive(Clone, Debug, Hash, PartialEq, Eq)] - pub struct Function { - address: *const VMFunctionBody, - _phantom: PhantomData<(Args, Rets)>, + /// Get the pointer to the function call trampoline. + fn call_trampoline_address() -> VMTrampoline; } - unsafe impl Send for Function {} - - impl Function - where - Args: WasmTypeList, - Rets: WasmTypeList, - { - /// Creates a new `Function`. - pub fn new(function: F) -> Self - where - F: HostFunction, - T: HostFunctionKind, - E: Sized, - { - Self { - address: function.function_body_ptr(), - _phantom: PhantomData, - } - } - - /// Get the function type of this `Function`. - pub fn ty(&self) -> FunctionType { - FunctionType::new(Args::wasm_types(), Rets::wasm_types()) - } - - /// Get the address of this `Function`. - pub fn address(&self) -> *const VMFunctionBody { - self.address - } + /// Represents a low-level Wasm static host function. See + /// `super::Function::new_native` to learn more. + pub(crate) struct StaticFunction { + pub(crate) raw_ctx: *mut u8, + pub(crate) func: F, } macro_rules! impl_host_function { @@ -1203,7 +937,7 @@ mod inner { /// A structure with a C-compatible representation that can hold a set of Wasm values. /// This type is used by `WasmTypeList::CStruct`. #[repr($c_struct_representation)] - pub struct $c_struct_name< $( $x ),* > ( $( <$x as FromToNativeWasmType>::Native ),* ) + pub struct $c_struct_name< $( $x ),* > ( $( <<$x as FromToNativeWasmType>::Native as NativeWasmType>::Abi ),* ) where $( $x: FromToNativeWasmType ),*; @@ -1218,10 +952,12 @@ mod inner { { type CStruct = $c_struct_name< $( $x ),* >; - type Array = [i128; count_idents!( $( $x ),* )]; + type Array = [RawValue; count_idents!( $( $x ),* )]; + #[allow(unused_mut)] #[allow(clippy::unused_unit)] - fn from_array(array: Self::Array) -> Self { + #[allow(clippy::missing_safety_doc)] + unsafe fn from_array(mut _ctx: impl AsContextMut, array: Self::Array) -> Self { // Unpack items of the array. #[allow(non_snake_case)] let [ $( $x ),* ] = array; @@ -1229,16 +965,19 @@ mod inner { // Build the tuple. ( $( - FromToNativeWasmType::from_native(NativeWasmType::from_binary($x)) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_ctx.as_context_mut(), $x)) ),* ) } - fn from_slice(slice: &[i128]) -> Result { - Ok(Self::from_array(slice.try_into()?)) + #[allow(clippy::missing_safety_doc)] + unsafe fn from_slice(ctx: impl AsContextMut, slice: &[RawValue]) -> Result { + Ok(Self::from_array(ctx, slice.try_into()?)) } - fn into_array(self) -> Self::Array { + #[allow(unused_mut)] + #[allow(clippy::missing_safety_doc)] + unsafe fn into_array(self, mut _ctx: impl AsContextMut) -> Self::Array { // Unpack items of the tuple. #[allow(non_snake_case)] let ( $( $x ),* ) = self; @@ -1246,38 +985,41 @@ mod inner { // Build the array. [ $( - FromToNativeWasmType::to_native($x).to_binary() + FromToNativeWasmType::to_native($x).into_raw(_ctx.as_context_mut()) ),* ] } fn empty_array() -> Self::Array { // Build an array initialized with `0`. - [0; count_idents!( $( $x ),* )] + [RawValue { i32: 0 }; count_idents!( $( $x ),* )] } + #[allow(unused_mut)] #[allow(clippy::unused_unit)] - fn from_c_struct(c_struct: Self::CStruct) -> Self { + #[allow(clippy::missing_safety_doc)] + unsafe fn from_c_struct(mut _ctx: impl AsContextMut, c_struct: Self::CStruct) -> Self { // Unpack items of the C structure. #[allow(non_snake_case)] let $c_struct_name( $( $x ),* ) = c_struct; ( $( - FromToNativeWasmType::from_native($x) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_ctx.as_context_mut(), $x)) ),* ) } - #[allow(unused_parens, non_snake_case)] - fn into_c_struct(self) -> Self::CStruct { + #[allow(unused_parens, non_snake_case, unused_mut)] + #[allow(clippy::missing_safety_doc)] + unsafe fn into_c_struct(self, mut _ctx: impl AsContextMut) -> Self::CStruct { // Unpack items of the tuple. let ( $( $x ),* ) = self; // Build the C structure. $c_struct_name( $( - FromToNativeWasmType::to_native($x) + FromToNativeWasmType::to_native($x).into_abi(_ctx.as_context_mut()) ),* ) } @@ -1292,91 +1034,49 @@ mod inner { } // Implement `HostFunction` for a function that has the same arity than the tuple. - // This specific function has no environment. #[allow(unused_parens)] - impl< $( $x, )* Rets, RetsAsResult, Func > - HostFunction<( $( $x ),* ), Rets, WithoutEnv, ()> + impl< $( $x, )* Rets, RetsAsResult, T, Func > + HostFunction for Func where $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Func: Fn($( $x , )*) -> RetsAsResult + 'static + Send, + Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, { #[allow(non_snake_case)] - fn function_body_ptr(self) -> *const VMFunctionBody { + fn function_body_ptr() -> *const VMFunctionBody { /// This is a function that wraps the real host /// function. Its address will be used inside the /// runtime. - extern fn func_wrapper<$( $x, )* Rets, RetsAsResult, Func>( _: usize, $( $x: $x::Native, )* ) -> Rets::CStruct + unsafe extern "C" fn func_wrapper( env: &StaticFunction, $( $x: $x::Native, )* ) -> Rets::CStruct where $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Func: Fn( $( $x ),* ) -> RetsAsResult + 'static + Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, { - let func: &Func = unsafe { &*(&() as *const () as *const Func) }; + let mut ctx = ContextMut::from_raw(env.raw_ctx as *mut ContextInner); + let result = on_host_stack(|| { panic::catch_unwind(AssertUnwindSafe(|| { - func( $( FromToNativeWasmType::from_native($x) ),* ).into_result() + (env.func)(ctx.as_context_mut(), $( FromToNativeWasmType::from_native($x) ),* ).into_result() })) }); match result { - Ok(Ok(result)) => return result.into_c_struct(), - Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) }, - Err(panic) => unsafe { resume_panic(panic) }, + Ok(Ok(result)) => return result.into_c_struct(ctx), + Ok(Err(trap)) => raise_user_trap(Box::new(trap)), + Err(panic) => resume_panic(panic) , } } - func_wrapper::< $( $x, )* Rets, RetsAsResult, Self > as *const VMFunctionBody + func_wrapper::< T, $( $x, )* Rets, RetsAsResult, Self > as *const VMFunctionBody } - } - - // Implement `HostFunction` for a function that has the same arity than the tuple. - // This specific function has an environment. - #[allow(unused_parens)] - impl< $( $x, )* Rets, RetsAsResult, Env, Func > - HostFunction<( $( $x ),* ), Rets, WithEnv, Env> - for - Func - where - $( $x: FromToNativeWasmType, )* - Rets: WasmTypeList, - RetsAsResult: IntoResult, - Env: Sized, - Func: Fn(&Env, $( $x , )*) -> RetsAsResult + Send + 'static, - { - #[allow(non_snake_case)] - fn function_body_ptr(self) -> *const VMFunctionBody { - /// This is a function that wraps the real host - /// function. Its address will be used inside the - /// runtime. - extern fn func_wrapper<$( $x, )* Rets, RetsAsResult, Env, Func>( env: &Env, $( $x: $x::Native, )* ) -> Rets::CStruct - where - $( $x: FromToNativeWasmType, )* - Rets: WasmTypeList, - RetsAsResult: IntoResult, - Env: Sized, - Func: Fn(&Env, $( $x ),* ) -> RetsAsResult + 'static - { - let func: &Func = unsafe { &*(&() as *const () as *const Func) }; - let result = on_host_stack(|| { - panic::catch_unwind(AssertUnwindSafe(|| { - func(env, $( FromToNativeWasmType::from_native($x) ),* ).into_result() - })) - }); - - match result { - Ok(Ok(result)) => return result.into_c_struct(), - Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) }, - Err(panic) => unsafe { resume_panic(panic) }, - } - } - - func_wrapper::< $( $x, )* Rets, RetsAsResult, Env, Self > as *const VMFunctionBody + fn call_trampoline_address() -> VMTrampoline { + todo!() } } }; @@ -1430,30 +1130,33 @@ mod inner { // fail (with `Result<_, Infallible>`). impl WasmTypeList for Infallible { type CStruct = Self; - type Array = [i128; 0]; + type Array = [RawValue; 0]; - fn from_array(_: Self::Array) -> Self { + unsafe fn from_array(_: impl AsContextMut, _: Self::Array) -> Self { unreachable!() } - fn from_slice(_: &[i128]) -> Result { + unsafe fn from_slice( + _: impl AsContextMut, + _: &[RawValue], + ) -> Result { unreachable!() } - fn into_array(self) -> Self::Array { + unsafe fn into_array(self, _: impl AsContextMut) -> Self::Array { [] } fn empty_array() -> Self::Array { - unreachable!() + [] } - fn from_c_struct(_: Self::CStruct) -> Self { - unreachable!() + unsafe fn from_c_struct(_: impl AsContextMut, self_: Self::CStruct) -> Self { + self_ } - fn into_c_struct(self) -> Self::CStruct { - unreachable!() + unsafe fn into_c_struct(self, _: impl AsContextMut) -> Self::CStruct { + self } fn wasm_types() -> &'static [Type] { @@ -1559,36 +1262,39 @@ mod inner { #[test] fn test_function_types() { - assert_eq!(Function::new(func).ty(), FunctionType::new(vec![], vec![])); assert_eq!( - Function::new(func__i32).ty(), + StaticFunction::new(func).ty(), + FunctionType::new(vec![], vec![]) + ); + assert_eq!( + StaticFunction::new(func__i32).ty(), FunctionType::new(vec![], vec![Type::I32]) ); assert_eq!( - Function::new(func_i32).ty(), + StaticFunction::new(func_i32).ty(), FunctionType::new(vec![Type::I32], vec![]) ); assert_eq!( - Function::new(func_i32__i32).ty(), + StaticFunction::new(func_i32__i32).ty(), FunctionType::new(vec![Type::I32], vec![Type::I32]) ); assert_eq!( - Function::new(func_i32_i32__i32).ty(), + StaticFunction::new(func_i32_i32__i32).ty(), FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]) ); assert_eq!( - Function::new(func_i32_i32__i32_i32).ty(), + StaticFunction::new(func_i32_i32__i32_i32).ty(), FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]) ); assert_eq!( - Function::new(func_f32_i32__i32_f32).ty(), + StaticFunction::new(func_f32_i32__i32_f32).ty(), FunctionType::new(vec![Type::F32, Type::I32], vec![Type::I32, Type::F32]) ); } #[test] fn test_function_pointer() { - let f = Function::new(func_i32__i32); + let f = StaticFunction::new(func_i32__i32); let function = unsafe { std::mem::transmute::<_, fn(usize, i32) -> i32>(f.address) }; assert_eq!(function(0, 3), 6); } diff --git a/lib/api/src/sys/externals/global.rs b/lib/api/src/sys/externals/global.rs index bb93e515174..a077847c05e 100644 --- a/lib/api/src/sys/externals/global.rs +++ b/lib/api/src/sys/externals/global.rs @@ -1,14 +1,11 @@ +use crate::sys::context::{AsContextMut, AsContextRef}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; -use crate::sys::store::{Store, StoreObject}; -use crate::sys::types::Val; +use crate::sys::value::Value; use crate::sys::GlobalType; use crate::sys::Mutability; use crate::sys::RuntimeError; -use std::fmt; -use std::sync::Arc; -use wasmer_compiler::Export; -use wasmer_vm::{Global as RuntimeGlobal, VMGlobal}; +use wasmer_vm::{ContextHandle, InternalContextHandle, VMExtern, VMGlobal}; /// A WebAssembly `global` instance. /// @@ -16,9 +13,9 @@ use wasmer_vm::{Global as RuntimeGlobal, VMGlobal}; /// It consists of an individual value and a flag indicating whether it is mutable. /// /// Spec: +#[derive(Debug, Clone)] pub struct Global { - store: Store, - vm_global: VMGlobal, + handle: ContextHandle, } impl Global { @@ -35,8 +32,8 @@ impl Global { /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Const); /// ``` - pub fn new(store: &Store, val: Val) -> Self { - Self::from_value(store, val, Mutability::Const).unwrap() + pub fn new(ctx: impl AsContextMut, val: Value) -> Self { + Self::from_value(ctx, val, Mutability::Const).unwrap() } /// Create a mutable `Global` with the initial value [`Val`]. @@ -52,31 +49,31 @@ impl Global { /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Var); /// ``` - pub fn new_mut(store: &Store, val: Val) -> Self { - Self::from_value(store, val, Mutability::Var).unwrap() + pub fn new_mut(ctx: impl AsContextMut, val: Value) -> Self { + Self::from_value(ctx, val, Mutability::Var).unwrap() } /// Create a `Global` with the initial value [`Val`] and the provided [`Mutability`]. - fn from_value(store: &Store, val: Val, mutability: Mutability) -> Result { - if !val.comes_from_same_store(store) { - return Err(RuntimeError::new("cross-`Store` globals are not supported")); + fn from_value( + mut ctx: impl AsContextMut, + val: Value, + mutability: Mutability, + ) -> Result { + if !val.is_from_context(ctx.as_context_mut()) { + return Err(RuntimeError::new( + "cross-`Context` values are not supported", + )); } - let global = RuntimeGlobal::new(GlobalType { + let global = VMGlobal::new(GlobalType { mutability, ty: val.ty(), }); unsafe { - global - .set_unchecked(val.clone()) - .map_err(|e| RuntimeError::new(format!("create global for {:?}: {}", val, e)))?; - }; + global.vmglobal().as_mut().val = val.as_raw(ctx.as_context_mut()); + } Ok(Self { - store: store.clone(), - vm_global: VMGlobal { - from: Arc::new(global), - instance_ref: None, - }, + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), global), }) } @@ -94,24 +91,8 @@ impl Global { /// assert_eq!(c.ty(), &GlobalType::new(Type::I32, Mutability::Const)); /// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var)); /// ``` - pub fn ty(&self) -> &GlobalType { - self.vm_global.from.ty() - } - - /// Returns the [`Store`] where the `Global` belongs. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); - /// # - /// let g = Global::new(&store, Value::I32(1)); - /// - /// assert_eq!(g.store(), &store); - /// ``` - pub fn store(&self) -> &Store { - &self.store + pub fn ty(&self, ctx: impl AsContextRef) -> GlobalType { + *self.handle.get(ctx.as_context_ref().objects()).ty() } /// Retrieves the current value [`Val`] that the Global has. @@ -126,8 +107,13 @@ impl Global { /// /// assert_eq!(g.get(), Value::I32(1)); /// ``` - pub fn get(&self) -> Val { - self.vm_global.from.get(&self.store) + pub fn get(&self, mut ctx: impl AsContextMut) -> Value { + unsafe { + let ctx = ctx.as_context_mut(); + let raw = self.handle.get(ctx.objects()).vmglobal().as_ref().val; + let ty = self.handle.get(ctx.objects()).ty().ty; + Value::from_raw(ctx, ty, raw) + } } /// Sets a custom value [`Val`] to the runtime Global. @@ -171,92 +157,58 @@ impl Global { /// // This results in an error: `RuntimeError`. /// g.set(Value::I64(2)).unwrap(); /// ``` - pub fn set(&self, val: Val) -> Result<(), RuntimeError> { - if !val.comes_from_same_store(&self.store) { - return Err(RuntimeError::new("cross-`Store` values are not supported")); + pub fn set(&self, mut ctx: impl AsContextMut, val: Value) -> Result<(), RuntimeError> { + if !val.is_from_context(ctx.as_context_mut()) { + return Err(RuntimeError::new( + "cross-`Context` values are not supported", + )); + } + if self.ty(ctx.as_context_mut()).mutability != Mutability::Var { + return Err(RuntimeError::new("Attempted to set an immutable global")); + } + if val.ty() != self.ty(ctx.as_context_mut()).ty { + return Err(RuntimeError::new(format!( + "Attempted to operate on a global of type {expected} as a global of type {found}", + expected = self.ty(ctx.as_context_mut()).ty, + found = val.ty(), + ))); } unsafe { - self.vm_global - .from - .set(val) - .map_err(|e| RuntimeError::new(format!("{}", e)))?; + self.handle + .get_mut(ctx.as_context_mut().objects_mut()) + .vmglobal() + .as_mut() + .val = val.as_raw(ctx.as_context_mut()); } Ok(()) } - pub(crate) fn from_vm_export(store: &Store, vm_global: VMGlobal) -> Self { + pub(crate) fn from_vm_extern( + ctx: impl AsContextMut, + internal: InternalContextHandle, + ) -> Self { Self { - store: store.clone(), - vm_global, + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, } } - /// Returns whether or not these two globals refer to the same data. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); - /// # - /// let g = Global::new(&store, Value::I32(1)); - /// - /// assert!(g.same(&g)); - /// ``` - pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.vm_global.from, &other.vm_global.from) - } - - /// Get access to the backing VM value for this extern. This function is for - /// tests it should not be called by users of the Wasmer API. - /// - /// # Safety - /// This function is unsafe to call outside of tests for the wasmer crate - /// because there is no stability guarantee for the returned type and we may - /// make breaking changes to it at any time or remove this method. - #[doc(hidden)] - pub unsafe fn get_vm_global(&self) -> &VMGlobal { - &self.vm_global - } -} - -impl Clone for Global { - fn clone(&self) -> Self { - let mut vm_global = self.vm_global.clone(); - vm_global.upgrade_instance_ref().unwrap(); - - Self { - store: self.store.clone(), - vm_global, - } + /// Checks whether this `Global` can be used with the given context. + pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } -} -impl fmt::Debug for Global { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter - .debug_struct("Global") - .field("ty", &self.ty()) - .field("value", &self.get()) - .finish() + pub(crate) fn to_vm_extern(&self) -> VMExtern { + VMExtern::Global(self.handle.internal_handle()) } } impl<'a> Exportable<'a> for Global { - fn to_export(&self) -> Export { - self.vm_global.clone().into() - } - fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Global(global) => Ok(global), _ => Err(ExportError::IncompatibleType), } } - - fn convert_to_weak_instance_ref(&mut self) { - if let Some(v) = self.vm_global.instance_ref.as_mut() { - *v = v.downgrade(); - } - } } diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 5bb4135d44b..081dc90011f 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -1,16 +1,17 @@ +use crate::sys::context::{AsContextMut, AsContextRef}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; -use crate::sys::store::Store; use crate::sys::MemoryType; -use crate::MemoryAccessError; +use crate::{ContextRef, MemoryAccessError}; use std::convert::TryInto; +use std::marker::PhantomData; use std::mem; use std::mem::MaybeUninit; use std::slice; -use std::sync::Arc; -use wasmer_compiler::Export; use wasmer_types::Pages; -use wasmer_vm::{MemoryError, VMMemory}; +use wasmer_vm::{ + ContextHandle, ContextObjects, InternalContextHandle, MemoryError, VMExtern, VMMemory, +}; /// A WebAssembly `memory` instance. /// @@ -26,10 +27,9 @@ use wasmer_vm::{MemoryError, VMMemory}; /// mutable from both host and WebAssembly. /// /// Spec: -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Memory { - store: Store, - vm_memory: VMMemory, + handle: ContextHandle, } impl Memory { @@ -46,19 +46,14 @@ impl Memory { /// # /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); /// ``` - pub fn new(store: &Store, ty: MemoryType) -> Result { - let tunables = store.tunables(); + pub fn new(mut ctx: impl AsContextMut, ty: MemoryType) -> Result { + let mut ctx = ctx.as_context_mut(); + let tunables = ctx.store().tunables(); let style = tunables.memory_style(&ty); let memory = tunables.create_host_memory(&ty, &style)?; Ok(Self { - store: store.clone(), - vm_memory: VMMemory { - from: memory, - // We are creating it from the host, and therefore there is no - // associated instance with this memory - instance_ref: None, - }, + handle: ContextHandle::new(ctx.objects_mut(), memory), }) } @@ -75,24 +70,8 @@ impl Memory { /// /// assert_eq!(m.ty(), mt); /// ``` - pub fn ty(&self) -> MemoryType { - self.vm_memory.from.ty() - } - - /// Returns the [`Store`] where the `Memory` belongs. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # let store = Store::default(); - /// # - /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); - /// - /// assert_eq!(m.store(), &store); - /// ``` - pub fn store(&self) -> &Store { - &self.store + pub fn ty(&self, ctx: impl AsContextRef) -> MemoryType { + self.handle.get(ctx.as_context_ref().objects()).ty() } /// Returns the pointer to the raw bytes of the `Memory`. @@ -100,17 +79,13 @@ impl Memory { // This used by wasmer-emscripten and wasmer-c-api, but should be treated // as deprecated and not used in future code. #[doc(hidden)] - pub fn data_ptr(&self) -> *mut u8 { - let definition = self.vm_memory.from.vmmemory(); - let def = unsafe { definition.as_ref() }; - def.base + pub fn data_ptr(&self, ctx: impl AsContextRef) -> *mut u8 { + self.buffer(ctx.as_context_ref()).base } /// Returns the size (in bytes) of the `Memory`. - pub fn data_size(&self) -> u64 { - let definition = self.vm_memory.from.vmmemory(); - let def = unsafe { definition.as_ref() }; - def.current_length.try_into().unwrap() + pub fn data_size(&self, ctx: impl AsContextRef) -> u64 { + self.buffer(ctx.as_context_ref()).len.try_into().unwrap() } /// Returns the size (in [`Pages`]) of the `Memory`. @@ -125,8 +100,8 @@ impl Memory { /// /// assert_eq!(m.size(), Pages(1)); /// ``` - pub fn size(&self) -> Pages { - self.vm_memory.from.size() + pub fn size(&self, ctx: impl AsContextRef) -> Pages { + self.handle.get(ctx.as_context_ref().objects()).size() } /// Grow memory by the specified amount of WebAssembly [`Pages`] and return @@ -159,46 +134,17 @@ impl Memory { /// // This results in an error: `MemoryError::CouldNotGrow`. /// let s = m.grow(1).unwrap(); /// ``` - pub fn grow(&self, delta: IntoPages) -> Result + pub fn grow( + &self, + mut ctx: impl AsContextMut, + delta: IntoPages, + ) -> Result where IntoPages: Into, { - self.vm_memory.from.grow(delta.into()) - } - - pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self { - Self { - store: store.clone(), - vm_memory, - } - } - - /// Returns whether or not these two memories refer to the same data. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Memory, MemoryType, Store, Value}; - /// # let store = Store::default(); - /// # - /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); - /// - /// assert!(m.same(&m)); - /// ``` - pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.vm_memory.from, &other.vm_memory.from) - } - - /// Get access to the backing VM value for this extern. This function is for - /// tests it should not be called by users of the Wasmer API. - /// - /// # Safety - /// This function is unsafe to call outside of tests for the wasmer crate - /// because there is no stability guarantee for the returned type and we may - /// make breaking changes to it at any time or remove this method. - #[doc(hidden)] - pub unsafe fn get_vm_memory(&self) -> &VMMemory { - &self.vm_memory + self.handle + .get_mut(ctx.as_context_mut().objects_mut()) + .grow(delta.into()) } /// Safely reads bytes from the memory at the given offset. @@ -208,20 +154,13 @@ impl Memory { /// /// This method is guaranteed to be safe (from the host side) in the face of /// concurrent writes. - pub fn read(&self, offset: u64, buf: &mut [u8]) -> Result<(), MemoryAccessError> { - let definition = self.vm_memory.from.vmmemory(); - let def = unsafe { definition.as_ref() }; - let end = offset - .checked_add(buf.len() as u64) - .ok_or(MemoryAccessError::Overflow)?; - if end > def.current_length.try_into().unwrap() { - return Err(MemoryAccessError::HeapOutOfBounds); - } - unsafe { - volatile_memcpy_read(def.base.add(offset as usize), buf.as_mut_ptr(), buf.len()); - } - - Ok(()) + pub fn read( + &self, + ctx: impl AsContextRef, + offset: u64, + buf: &mut [u8], + ) -> Result<(), MemoryAccessError> { + self.buffer(ctx.as_context_ref()).read(offset, buf) } /// Safely reads bytes from the memory at the given offset. @@ -236,23 +175,11 @@ impl Memory { /// concurrent writes. pub fn read_uninit<'a>( &self, + ctx: impl AsContextRef, offset: u64, buf: &'a mut [MaybeUninit], ) -> Result<&'a mut [u8], MemoryAccessError> { - let definition = self.vm_memory.from.vmmemory(); - let def = unsafe { definition.as_ref() }; - let end = offset - .checked_add(buf.len() as u64) - .ok_or(MemoryAccessError::Overflow)?; - if end > def.current_length.try_into().unwrap() { - return Err(MemoryAccessError::HeapOutOfBounds); - } - let buf_ptr = buf.as_mut_ptr() as *mut u8; - unsafe { - volatile_memcpy_read(def.base.add(offset as usize), buf_ptr, buf.len()); - } - - Ok(unsafe { slice::from_raw_parts_mut(buf_ptr, buf.len()) }) + self.buffer(ctx.as_context_ref()).read_uninit(offset, buf) } /// Safely writes bytes to the memory at the given offset. @@ -262,50 +189,107 @@ impl Memory { /// /// This method is guaranteed to be safe (from the host side) in the face of /// concurrent reads/writes. - pub fn write(&self, offset: u64, data: &[u8]) -> Result<(), MemoryAccessError> { - let definition = self.vm_memory.from.vmmemory(); + pub fn write( + &self, + ctx: impl AsContextRef, + offset: u64, + data: &[u8], + ) -> Result<(), MemoryAccessError> { + self.buffer(ctx.as_context_ref()).write(offset, data) + } + + pub(crate) fn buffer<'a, U>(&'a self, ctx: ContextRef<'a, U>) -> MemoryBuffer<'a> { + let definition = self.handle.get(ctx.objects()).vmmemory(); let def = unsafe { definition.as_ref() }; - let end = offset - .checked_add(data.len() as u64) - .ok_or(MemoryAccessError::Overflow)?; - if end > def.current_length.try_into().unwrap() { - return Err(MemoryAccessError::HeapOutOfBounds); + MemoryBuffer { + base: def.base, + len: def.current_length, + marker: PhantomData, } - unsafe { - volatile_memcpy_write(data.as_ptr(), def.base.add(offset as usize), data.len()); - } - Ok(()) } -} - -impl Clone for Memory { - fn clone(&self) -> Self { - let mut vm_memory = self.vm_memory.clone(); - vm_memory.upgrade_instance_ref().unwrap(); + pub(crate) fn from_vm_extern( + ctx: impl AsContextRef, + internal: InternalContextHandle, + ) -> Self { Self { - store: self.store.clone(), - vm_memory, + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, } } -} -impl<'a> Exportable<'a> for Memory { - fn to_export(&self) -> Export { - self.vm_memory.clone().into() + /// Checks whether this `Memory` can be used with the given context. + pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } + pub(crate) fn to_vm_extern(&self) -> VMExtern { + VMExtern::Memory(self.handle.internal_handle()) + } +} + +impl<'a> Exportable<'a> for Memory { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Memory(memory) => Ok(memory), _ => Err(ExportError::IncompatibleType), } } +} + +/// Underlying buffer for a memory. +#[derive(Copy, Clone)] +pub(crate) struct MemoryBuffer<'a> { + base: *mut u8, + len: usize, + marker: PhantomData<(&'a Memory, &'a ContextObjects)>, +} + +impl<'a> MemoryBuffer<'a> { + pub(crate) fn read(&self, offset: u64, buf: &mut [u8]) -> Result<(), MemoryAccessError> { + let end = offset + .checked_add(buf.len() as u64) + .ok_or(MemoryAccessError::Overflow)?; + if end > self.len.try_into().unwrap() { + return Err(MemoryAccessError::HeapOutOfBounds); + } + unsafe { + volatile_memcpy_read(self.base.add(offset as usize), buf.as_mut_ptr(), buf.len()); + } + Ok(()) + } + + pub(crate) fn read_uninit<'b>( + &self, + offset: u64, + buf: &'b mut [MaybeUninit], + ) -> Result<&'b mut [u8], MemoryAccessError> { + let end = offset + .checked_add(buf.len() as u64) + .ok_or(MemoryAccessError::Overflow)?; + if end > self.len.try_into().unwrap() { + return Err(MemoryAccessError::HeapOutOfBounds); + } + let buf_ptr = buf.as_mut_ptr() as *mut u8; + unsafe { + volatile_memcpy_read(self.base.add(offset as usize), buf_ptr, buf.len()); + } + + Ok(unsafe { slice::from_raw_parts_mut(buf_ptr, buf.len()) }) + } - fn convert_to_weak_instance_ref(&mut self) { - if let Some(v) = self.vm_memory.instance_ref.as_mut() { - *v = v.downgrade(); + pub(crate) fn write(&self, offset: u64, data: &[u8]) -> Result<(), MemoryAccessError> { + let end = offset + .checked_add(data.len() as u64) + .ok_or(MemoryAccessError::Overflow)?; + if end > self.len.try_into().unwrap() { + return Err(MemoryAccessError::HeapOutOfBounds); } + unsafe { + volatile_memcpy_write(data.as_ptr(), self.base.add(offset as usize), data.len()); + } + Ok(()) } } diff --git a/lib/api/src/sys/externals/mod.rs b/lib/api/src/sys/externals/mod.rs index df58d31df56..e0e944d6415 100644 --- a/lib/api/src/sys/externals/mod.rs +++ b/lib/api/src/sys/externals/mod.rs @@ -1,21 +1,20 @@ pub(crate) mod function; -mod global; -mod memory; -mod table; +pub(crate) mod global; +pub(crate) mod memory; +pub(crate) mod table; -pub use self::function::{ - FromToNativeWasmType, Function, HostFunction, WasmTypeList, WithEnv, WithoutEnv, -}; +pub use self::function::{FromToNativeWasmType, Function, HostFunction, WasmTypeList}; pub use self::global::Global; pub use self::memory::Memory; pub use self::table::Table; use crate::sys::exports::{ExportError, Exportable}; -use crate::sys::store::{Store, StoreObject}; use crate::sys::ExternType; use std::fmt; -use wasmer_compiler::Export; +use wasmer_vm::VMExtern; + +use super::context::{AsContextMut, AsContextRef}; /// An `Extern` is the runtime representation of an entity that /// can be imported or exported. @@ -35,60 +34,49 @@ pub enum Extern { impl Extern { /// Return the underlying type of the inner `Extern`. - pub fn ty(&self) -> ExternType { + pub fn ty(&self, ctx: impl AsContextRef) -> ExternType { match self { - Self::Function(ft) => ExternType::Function(ft.ty().clone()), - Self::Memory(ft) => ExternType::Memory(ft.ty()), - Self::Table(tt) => ExternType::Table(*tt.ty()), - Self::Global(gt) => ExternType::Global(*gt.ty()), + Self::Function(ft) => ExternType::Function(ft.ty(ctx)), + Self::Memory(ft) => ExternType::Memory(ft.ty(ctx)), + Self::Table(tt) => ExternType::Table(tt.ty(ctx)), + Self::Global(gt) => ExternType::Global(gt.ty(ctx)), } } - /// Create an `Extern` from an `wasmer_compiler::Export`. - pub fn from_vm_export(store: &Store, export: Export) -> Self { - match export { - Export::Function(f) => Self::Function(Function::from_vm_export(store, f)), - Export::Memory(m) => Self::Memory(Memory::from_vm_export(store, m)), - Export::Global(g) => Self::Global(Global::from_vm_export(store, g)), - Export::Table(t) => Self::Table(Table::from_vm_export(store, t)), + /// Create an `Extern` from an `wasmer_engine::Export`. + pub(crate) fn from_vm_extern(ctx: impl AsContextMut, vm_extern: VMExtern) -> Self { + match vm_extern { + VMExtern::Function(f) => Self::Function(Function::from_vm_extern(ctx, f)), + VMExtern::Memory(m) => Self::Memory(Memory::from_vm_extern(ctx, m)), + VMExtern::Global(g) => Self::Global(Global::from_vm_extern(ctx, g)), + VMExtern::Table(t) => Self::Table(Table::from_vm_extern(ctx, t)), } } -} -impl<'a> Exportable<'a> for Extern { - fn to_export(&self) -> Export { + /// Checks whether this `Extern` can be used with the given context. + pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { match self { - Self::Function(f) => f.to_export(), - Self::Global(g) => g.to_export(), - Self::Memory(m) => m.to_export(), - Self::Table(t) => t.to_export(), + Self::Function(f) => f.is_from_context(ctx), + Self::Global(g) => g.is_from_context(ctx), + Self::Memory(m) => m.is_from_context(ctx), + Self::Table(t) => t.is_from_context(ctx), } } - fn get_self_from_extern(_extern: &'a Self) -> Result<&'a Self, ExportError> { - // Since this is already an extern, we can just return it. - Ok(_extern) - } - - fn convert_to_weak_instance_ref(&mut self) { + pub(crate) fn to_vm_extern(&self) -> VMExtern { match self { - Self::Function(f) => f.convert_to_weak_instance_ref(), - Self::Global(g) => g.convert_to_weak_instance_ref(), - Self::Memory(m) => m.convert_to_weak_instance_ref(), - Self::Table(t) => t.convert_to_weak_instance_ref(), + Self::Function(f) => f.to_vm_extern(), + Self::Global(g) => g.to_vm_extern(), + Self::Memory(m) => m.to_vm_extern(), + Self::Table(t) => t.to_vm_extern(), } } } -impl StoreObject for Extern { - fn comes_from_same_store(&self, store: &Store) -> bool { - let my_store = match self { - Self::Function(f) => f.store(), - Self::Global(g) => g.store(), - Self::Memory(m) => m.store(), - Self::Table(t) => t.store(), - }; - Store::same(my_store, store) +impl<'a> Exportable<'a> for Extern { + fn get_self_from_extern(_extern: &'a Self) -> Result<&'a Self, ExportError> { + // Since this is already an extern, we can just return it. + Ok(_extern) } } diff --git a/lib/api/src/sys/externals/table.rs b/lib/api/src/sys/externals/table.rs index d7a11013b30..ed07478696f 100644 --- a/lib/api/src/sys/externals/table.rs +++ b/lib/api/src/sys/externals/table.rs @@ -1,12 +1,10 @@ +use crate::sys::context::{AsContextMut, AsContextRef}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; -use crate::sys::store::Store; -use crate::sys::types::{Val, ValFuncRef}; use crate::sys::RuntimeError; use crate::sys::TableType; -use std::sync::Arc; -use wasmer_compiler::Export; -use wasmer_vm::{Table as RuntimeTable, TableElement, VMTable}; +use crate::{ExternRef, Function, Value}; +use wasmer_vm::{ContextHandle, InternalContextHandle, TableElement, VMExtern, VMTable}; /// A WebAssembly `table` instance. /// @@ -17,19 +15,48 @@ use wasmer_vm::{Table as RuntimeTable, TableElement, VMTable}; /// mutable from both host and WebAssembly. /// /// Spec: +#[derive(Debug, Clone)] pub struct Table { - store: Store, - vm_table: VMTable, + handle: ContextHandle, } fn set_table_item( - table: &dyn RuntimeTable, + table: &mut VMTable, item_index: u32, item: TableElement, ) -> Result<(), RuntimeError> { table.set(item_index, item).map_err(|e| e.into()) } +fn value_to_table_element( + ctx: impl AsContextMut, + val: Value, +) -> Result { + if !val.is_from_context(ctx.as_context_ref()) { + return Err(RuntimeError::new("cannot pass Value across contexts")); + } + Ok(match val { + Value::ExternRef(extern_ref) => { + wasmer_vm::TableElement::ExternRef(extern_ref.map(|e| e.vm_externref())) + } + Value::FuncRef(func_ref) => { + wasmer_vm::TableElement::FuncRef(func_ref.map(|f| f.vm_funcref(ctx))) + } + _ => return Err(RuntimeError::new("val is not reference")), + }) +} + +fn value_from_table_element(ctx: impl AsContextMut, item: wasmer_vm::TableElement) -> Value { + match item { + wasmer_vm::TableElement::FuncRef(funcref) => { + Value::FuncRef(funcref.map(|f| unsafe { Function::from_vm_funcref(ctx, f) })) + } + wasmer_vm::TableElement::ExternRef(extern_ref) => { + Value::ExternRef(extern_ref.map(|e| unsafe { ExternRef::from_vm_externref(ctx, e) })) + } + } +} + impl Table { /// Creates a new `Table` with the provided [`TableType`] definition. /// @@ -37,53 +64,58 @@ impl Table { /// /// This function will construct the `Table` using the store /// [`BaseTunables`][crate::sys::BaseTunables]. - pub fn new(store: &Store, ty: TableType, init: Val) -> Result { - let item = init.into_table_reference(store)?; - let tunables = store.tunables(); + pub fn new( + mut ctx: impl AsContextMut, + ty: TableType, + init: Value, + ) -> Result { + let mut ctx = ctx.as_context_mut(); + let item = value_to_table_element(ctx.as_context_mut(), init)?; + let tunables = ctx.store().tunables(); let style = tunables.table_style(&ty); - let table = tunables + let mut table = tunables .create_host_table(&ty, &style) .map_err(RuntimeError::new)?; let num_elements = table.size(); for i in 0..num_elements { - set_table_item(table.as_ref(), i, item.clone())?; + set_table_item(&mut table, i, item.clone())?; } Ok(Self { - store: store.clone(), - vm_table: VMTable { - from: table, - instance_ref: None, - }, + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), table), }) } /// Returns the [`TableType`] of the `Table`. - pub fn ty(&self) -> &TableType { - self.vm_table.from.ty() - } - - /// Returns the [`Store`] where the `Table` belongs. - pub fn store(&self) -> &Store { - &self.store + pub fn ty(&self, ctx: impl AsContextRef) -> TableType { + *self.handle.get(ctx.as_context_ref().objects()).ty() } /// Retrieves an element of the table at the provided `index`. - pub fn get(&self, index: u32) -> Option { - let item = self.vm_table.from.get(index)?; - Some(ValFuncRef::from_table_reference(item, &self.store)) + pub fn get(&self, ctx: impl AsContextMut, index: u32) -> Option { + let item = self.handle.get(ctx.as_context_ref().objects()).get(index)?; + Some(value_from_table_element(ctx, item)) } /// Sets an element `val` in the Table at the provided `index`. - pub fn set(&self, index: u32, val: Val) -> Result<(), RuntimeError> { - let item = val.into_table_reference(&self.store)?; - set_table_item(self.vm_table.from.as_ref(), index, item) + pub fn set( + &self, + mut ctx: impl AsContextMut, + index: u32, + val: Value, + ) -> Result<(), RuntimeError> { + let item = value_to_table_element(ctx.as_context_mut(), val)?; + set_table_item( + self.handle.get_mut(ctx.as_context_mut().objects_mut()), + index, + item, + ) } /// Retrieves the size of the `Table` (in elements) - pub fn size(&self) -> u32 { - self.vm_table.from.size() + pub fn size(&self, ctx: impl AsContextRef) -> u32 { + self.handle.get(ctx.as_context_ref().objects()).size() } /// Grows the size of the `Table` by `delta`, initializating @@ -95,10 +127,15 @@ impl Table { /// # Errors /// /// Returns an error if the `delta` is out of bounds for the table. - pub fn grow(&self, delta: u32, init: Val) -> Result { - let item = init.into_table_reference(&self.store)?; - self.vm_table - .from + pub fn grow( + &self, + mut ctx: impl AsContextMut, + delta: u32, + init: Value, + ) -> Result { + let item = value_to_table_element(ctx.as_context_mut(), init)?; + self.handle + .get_mut(ctx.as_context_mut().objects_mut()) .grow(delta, item) .ok_or_else(|| RuntimeError::new(format!("failed to grow table by `{}`", delta))) } @@ -111,80 +148,59 @@ impl Table { /// Returns an error if the range is out of bounds of either the source or /// destination tables. pub fn copy( + mut ctx: impl AsContextMut, dst_table: &Self, dst_index: u32, src_table: &Self, src_index: u32, len: u32, ) -> Result<(), RuntimeError> { - if !Store::same(&dst_table.store, &src_table.store) { + if dst_table.handle.context_id() != src_table.handle.context_id() { return Err(RuntimeError::new( - "cross-`Store` table copies are not supported", + "cross-`Context` table copies are not supported", )); } - RuntimeTable::copy( - dst_table.vm_table.from.as_ref(), - src_table.vm_table.from.as_ref(), - dst_index, - src_index, - len, - ) + let mut ctx = ctx.as_context_mut(); + if dst_table.handle.internal_handle() == src_table.handle.internal_handle() { + let table = dst_table.handle.get_mut(ctx.objects_mut()); + table.copy_within(dst_index, src_index, len) + } else { + let (src_table, dst_table) = ctx.objects_mut().get_2_mut( + src_table.handle.internal_handle(), + dst_table.handle.internal_handle(), + ); + VMTable::copy(dst_table, src_table, dst_index, src_index, len) + } .map_err(RuntimeError::from_trap)?; Ok(()) } - pub(crate) fn from_vm_export(store: &Store, vm_table: VMTable) -> Self { + pub(crate) fn from_vm_extern( + ctx: impl AsContextMut, + internal: InternalContextHandle, + ) -> Self { Self { - store: store.clone(), - vm_table, + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, } } - /// Returns whether or not these two tables refer to the same data. - pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.vm_table.from, &other.vm_table.from) + /// Checks whether this `Table` can be used with the given context. + pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } - /// Get access to the backing VM value for this extern. This function is for - /// tests it should not be called by users of the Wasmer API. - /// - /// # Safety - /// This function is unsafe to call outside of tests for the wasmer crate - /// because there is no stability guarantee for the returned type and we may - /// make breaking changes to it at any time or remove this method. - #[doc(hidden)] - pub unsafe fn get_vm_table(&self) -> &VMTable { - &self.vm_table - } -} - -impl Clone for Table { - fn clone(&self) -> Self { - let mut vm_table = self.vm_table.clone(); - vm_table.upgrade_instance_ref().unwrap(); - - Self { - store: self.store.clone(), - vm_table, - } + pub(crate) fn to_vm_extern(&self) -> VMExtern { + VMExtern::Table(self.handle.internal_handle()) } } impl<'a> Exportable<'a> for Table { - fn to_export(&self) -> Export { - self.vm_table.clone().into() - } - fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Table(table) => Ok(table), _ => Err(ExportError::IncompatibleType), } } - - fn convert_to_weak_instance_ref(&mut self) { - if let Some(v) = self.vm_table.instance_ref.as_mut() { - *v = v.downgrade(); - } - } } diff --git a/lib/api/src/sys/imports.rs b/lib/api/src/sys/imports.rs index 9a0c94c402c..458108a852f 100644 --- a/lib/api/src/sys/imports.rs +++ b/lib/api/src/sys/imports.rs @@ -286,7 +286,7 @@ mod test { let happy_dog_entry = imports1.get_export("dog", "happy").unwrap(); assert!( - if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() { + if let Export::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { happy_dog_global.from.ty().ty == Type::I32 } else { false @@ -399,7 +399,7 @@ mod test { let happy_dog_entry = imports1.get_export("dog", "happy").unwrap(); assert!( - if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() { + if let Export::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { happy_dog_global.from.ty().ty == Type::I64 } else { false @@ -427,7 +427,7 @@ mod test { let happy_dog_entry = imports2.get_export("dog", "happy").unwrap(); assert!( - if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() { + if let Export::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { happy_dog_global.from.ty().ty == Type::I32 } else { false diff --git a/lib/api/src/sys/instance.rs b/lib/api/src/sys/instance.rs index b80f44e2261..9cccf7cf2e0 100644 --- a/lib/api/src/sys/instance.rs +++ b/lib/api/src/sys/instance.rs @@ -2,12 +2,12 @@ use crate::sys::exports::Exports; use crate::sys::externals::Extern; use crate::sys::imports::Imports; use crate::sys::module::Module; -use crate::sys::store::Store; -use crate::sys::{HostEnvInitError, LinkError, RuntimeError}; +use crate::sys::{LinkError, RuntimeError}; use std::fmt; -use std::sync::{Arc, Mutex}; use thiserror::Error; -use wasmer_vm::{InstanceHandle, VMContext}; +use wasmer_vm::{ContextHandle, InstanceHandle}; + +use super::context::AsContextMut; /// A WebAssembly Instance is a stateful, executable /// instance of a WebAssembly [`Module`]. @@ -19,10 +19,8 @@ use wasmer_vm::{InstanceHandle, VMContext}; /// Spec: #[derive(Clone)] pub struct Instance { - handle: Arc>, + _handle: ContextHandle, module: Module, - #[allow(dead_code)] - imports: Vec, /// The exports for an instance. pub exports: Exports, } @@ -64,9 +62,10 @@ pub enum InstantiationError { #[error("missing requires CPU features: {0:?}")] CpuFeature(String), - /// Error occurred when initializing the host environment. - #[error(transparent)] - HostEnvInitialization(HostEnvInitError), + /// Import from a different [`Context`]. + /// This error occurs when an import from a different context is used. + #[error("cannot mix imports from different contexts")] + BadContext, } impl From for InstantiationError { @@ -79,12 +78,6 @@ impl From for InstantiationError { } } -impl From for InstantiationError { - fn from(other: HostEnvInitError) -> Self { - Self::HostEnvInitialization(other) - } -} - impl Instance { /// Creates a new `Instance` from a WebAssembly [`Module`] and a /// set of imports using [`Imports`] or the [`imports`] macro helper. @@ -114,45 +107,31 @@ impl Instance { /// Those are, as defined by the spec: /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. - pub fn new(module: &Module, imports: &Imports) -> Result { - let store = module.store(); + pub fn new( + mut ctx: impl AsContextMut, + module: &Module, + imports: &Imports, + ) -> Result { let imports = imports .imports_for_module(module) .map_err(InstantiationError::Link)?; - let handle = module.instantiate(&imports)?; + let mut handle = module.instantiate(ctx.as_context_mut(), &imports)?; let exports = module .exports() .map(|export| { let name = export.name().to_string(); let export = handle.lookup(&name).expect("export"); - let extern_ = Extern::from_vm_export(store, export.into()); + let extern_ = Extern::from_vm_extern(ctx.as_context_mut(), export); (name, extern_) }) .collect::(); let instance = Self { - handle: Arc::new(Mutex::new(handle)), + _handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), handle), module: module.clone(), - imports, exports, }; - // # Safety - // `initialize_host_envs` should be called after instantiation but before - // returning an `Instance` to the user. We set up the host environments - // via `WasmerEnv::init_with_instance`. - // - // This usage is correct because we pass a valid pointer to `instance` and the - // correct error type returned by `WasmerEnv::init_with_instance` as a generic - // parameter. - unsafe { - instance - .handle - .lock() - .unwrap() - .initialize_host_envs::(&instance as *const _ as *const _)?; - } - Ok(instance) } @@ -166,43 +145,29 @@ impl Instance { /// Those are, as defined by the spec: /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. - pub fn new_by_index(module: &Module, externs: &[Extern]) -> Result { - let store = module.store(); + pub fn new_by_index( + mut ctx: impl AsContextMut, + module: &Module, + externs: &[Extern], + ) -> Result { let imports = externs.to_vec(); - let handle = module.instantiate(&imports)?; + let mut handle = module.instantiate(ctx.as_context_mut(), &imports)?; let exports = module .exports() .map(|export| { let name = export.name().to_string(); let export = handle.lookup(&name).expect("export"); - let extern_ = Extern::from_vm_export(store, export.into()); + let extern_ = Extern::from_vm_extern(ctx.as_context_mut(), export); (name, extern_) }) .collect::(); let instance = Self { - handle: Arc::new(Mutex::new(handle)), + _handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), handle), module: module.clone(), - imports, exports, }; - // # Safety - // `initialize_host_envs` should be called after instantiation but before - // returning an `Instance` to the user. We set up the host environments - // via `WasmerEnv::init_with_instance`. - // - // This usage is correct because we pass a valid pointer to `instance` and the - // correct error type returned by `WasmerEnv::init_with_instance` as a generic - // parameter. - unsafe { - instance - .handle - .lock() - .unwrap() - .initialize_host_envs::(&instance as *const _ as *const _)?; - } - Ok(instance) } @@ -210,16 +175,6 @@ impl Instance { pub fn module(&self) -> &Module { &self.module } - - /// Returns the [`Store`] where the `Instance` belongs. - pub fn store(&self) -> &Store { - self.module.store() - } - - #[doc(hidden)] - pub fn vmctx_ptr(&self) -> *mut VMContext { - self.handle.lock().unwrap().vmctx_ptr() - } } impl fmt::Debug for Instance { diff --git a/lib/api/src/sys/mem_access.rs b/lib/api/src/sys/mem_access.rs index 00d7f7144b4..db913a71b85 100644 --- a/lib/api/src/sys/mem_access.rs +++ b/lib/api/src/sys/mem_access.rs @@ -12,6 +12,9 @@ use std::{ use thiserror::Error; use wasmer_types::ValueType; +use super::context::AsContextRef; +use super::externals::memory::MemoryBuffer; + /// Error for invalid [`Memory`] access. #[derive(Clone, Copy, Debug, Error)] #[non_exhaustive] @@ -51,7 +54,7 @@ impl From for MemoryAccessError { /// thread. #[derive(Clone, Copy)] pub struct WasmRef<'a, T: ValueType> { - memory: &'a Memory, + buffer: MemoryBuffer<'a>, offset: u64, marker: PhantomData<*mut T>, } @@ -59,9 +62,9 @@ pub struct WasmRef<'a, T: ValueType> { impl<'a, T: ValueType> WasmRef<'a, T> { /// Creates a new `WasmRef` at the given offset in a memory. #[inline] - pub fn new(memory: &'a Memory, offset: u64) -> Self { + pub fn new(ctx: &'a impl AsContextRef, memory: &'a Memory, offset: u64) -> Self { Self { - memory, + buffer: memory.buffer(ctx.as_context_ref()), offset, marker: PhantomData, } @@ -96,19 +99,13 @@ impl<'a, T: ValueType> WasmRef<'a, T> { WasmPtr::::new(offset) } - /// Get a reference to the Wasm memory backing this reference. - #[inline] - pub fn memory(self) -> &'a Memory { - self.memory - } - /// Reads the location pointed to by this `WasmRef`. #[inline] pub fn read(self) -> Result { let mut out = MaybeUninit::uninit(); let buf = unsafe { slice::from_raw_parts_mut(out.as_mut_ptr() as *mut u8, mem::size_of::()) }; - self.memory.read(self.offset, buf)?; + self.buffer.read(self.offset, buf)?; Ok(unsafe { out.assume_init() }) } @@ -124,7 +121,7 @@ impl<'a, T: ValueType> WasmRef<'a, T> { }; val.zero_padding_bytes(data); let data = unsafe { slice::from_raw_parts(data.as_ptr() as *const _, data.len()) }; - self.memory.write(self.offset, data) + self.buffer.write(self.offset, data) } } @@ -151,7 +148,7 @@ impl<'a, T: ValueType> fmt::Debug for WasmRef<'a, T> { /// thread. #[derive(Clone, Copy)] pub struct WasmSlice<'a, T: ValueType> { - memory: &'a Memory, + buffer: MemoryBuffer<'a>, offset: u64, len: u64, marker: PhantomData<*mut T>, @@ -163,7 +160,12 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { /// /// Returns a `MemoryAccessError` if the slice length overflows. #[inline] - pub fn new(memory: &'a Memory, offset: u64, len: u64) -> Result { + pub fn new( + ctx: &'a impl AsContextRef, + memory: &'a Memory, + offset: u64, + len: u64, + ) -> Result { let total_len = len .checked_mul(mem::size_of::() as u64) .ok_or(MemoryAccessError::Overflow)?; @@ -171,7 +173,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { .checked_add(total_len) .ok_or(MemoryAccessError::Overflow)?; Ok(Self { - memory, + buffer: memory.buffer(ctx.as_context_ref()), offset, len, marker: PhantomData, @@ -208,12 +210,6 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { self.len == 0 } - /// Get a reference to the Wasm memory backing this reference. - #[inline] - pub fn memory(self) -> &'a Memory { - self.memory - } - /// Get a `WasmRef` to an element in the slice. #[inline] pub fn index(self, idx: u64) -> WasmRef<'a, T> { @@ -222,7 +218,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { } let offset = self.offset + idx * mem::size_of::() as u64; WasmRef { - memory: self.memory, + buffer: self.buffer, offset, marker: PhantomData, } @@ -236,7 +232,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { } let offset = self.offset + range.start * mem::size_of::() as u64; Self { - memory: self.memory, + buffer: self.buffer, offset, len: range.end - range.start, marker: PhantomData, @@ -277,7 +273,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { buf.len() * mem::size_of::(), ) }; - self.memory.read_uninit(self.offset, bytes)?; + self.buffer.read_uninit(self.offset, bytes)?; Ok(()) } @@ -302,7 +298,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { buf.len() * mem::size_of::(), ) }; - self.memory.read_uninit(self.offset, bytes)?; + self.buffer.read_uninit(self.offset, bytes)?; Ok(unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut T, buf.len()) }) } @@ -319,7 +315,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { let bytes = unsafe { slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * mem::size_of::()) }; - self.memory.write(self.offset, bytes) + self.buffer.write(self.offset, bytes) } /// Reads this `WasmSlice` into a `Vec`. @@ -333,7 +329,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { len * mem::size_of::(), ) }; - self.memory.read_uninit(self.offset, bytes)?; + self.buffer.read_uninit(self.offset, bytes)?; unsafe { vec.set_len(len); } diff --git a/lib/api/src/sys/mod.rs b/lib/api/src/sys/mod.rs index db67e5428ff..e9e4ce3a40d 100644 --- a/lib/api/src/sys/mod.rs +++ b/lib/api/src/sys/mod.rs @@ -1,33 +1,21 @@ -mod env; +mod context; mod exports; +mod extern_ref; mod externals; mod imports; mod instance; mod mem_access; mod module; mod native; +mod native_type; mod ptr; mod store; mod tunables; -mod types; +mod value; -/// Implement [`WasmerEnv`] for your type with `#[derive(WasmerEnv)]`. -/// -/// See the [`WasmerEnv`] trait for more information. -pub use wasmer_derive::WasmerEnv; - -#[doc(hidden)] -pub mod internals { - //! We use the internals module for exporting types that are only - //! intended to use in internal crates such as the compatibility crate - //! `wasmer-vm`. Please don't use any of this types directly, as - //! they might change frequently or be removed in the future. - - pub use crate::sys::externals::{WithEnv, WithoutEnv}; -} - -pub use crate::sys::env::{HostEnvInitError, LazyInit, WasmerEnv}; +pub use crate::sys::context::{AsContextMut, AsContextRef, Context, ContextMut, ContextRef}; pub use crate::sys::exports::{ExportError, Exportable, Exports, ExportsIterator}; +pub use crate::sys::extern_ref::ExternRef; pub use crate::sys::externals::{ Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, Table, WasmTypeList, }; @@ -36,27 +24,27 @@ pub use crate::sys::instance::{Instance, InstantiationError}; pub use crate::sys::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter}; pub use crate::sys::module::Module; pub use crate::sys::native::TypedFunction; +pub use crate::sys::native_type::NativeWasmTypeInto; pub use crate::sys::ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64}; -pub use crate::sys::store::{Store, StoreObject}; +pub use crate::sys::store::Store; pub use crate::sys::tunables::BaseTunables; -pub use crate::sys::types::{ - ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, - TableType, Val, ValType, -}; -pub use crate::sys::types::{Val as Value, ValType as Type}; +pub use crate::sys::value::Value; pub use target_lexicon::{Architecture, CallingConvention, OperatingSystem, Triple, HOST}; #[cfg(feature = "compiler")] pub use wasmer_compiler::{ wasmparser, CompilerConfig, FunctionMiddleware, MiddlewareReaderState, ModuleMiddleware, }; pub use wasmer_compiler::{ - CpuFeature, Engine, Export, Features, FrameInfo, LinkError, RuntimeError, Target, Tunables, + CpuFeature, Engine, Features, FrameInfo, LinkError, RuntimeError, Target, Tunables, }; pub use wasmer_derive::ValueType; pub use wasmer_types::is_wasm; -#[cfg(feature = "experimental-reference-types-extern-ref")] -pub use wasmer_types::ExternRef; +pub use wasmer_types::{ + ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, + TableType, Type, +}; + pub use wasmer_types::{ Bytes, CompileError, DeserializeError, ExportIndex, GlobalInit, LocalFunctionIndex, MiddlewareError, Pages, ParseCpuFeatureError, SerializeError, ValueType, WasmError, WasmResult, @@ -69,7 +57,7 @@ pub mod vm { //! The `vm` module re-exports wasmer-vm types. pub use wasmer_vm::{ - Memory, MemoryError, MemoryStyle, Table, TableStyle, VMExtern, VMMemoryDefinition, + MemoryError, MemoryStyle, TableStyle, VMExtern, VMMemory, VMMemoryDefinition, VMTable, VMTableDefinition, }; } diff --git a/lib/api/src/sys/module.rs b/lib/api/src/sys/module.rs index 77d69980ca1..241981109bd 100644 --- a/lib/api/src/sys/module.rs +++ b/lib/api/src/sys/module.rs @@ -1,6 +1,4 @@ -use crate::sys::exports::Exportable; use crate::sys::store::Store; -use crate::sys::types::{ExportType, ImportType}; use crate::sys::InstantiationError; use std::fmt; use std::io; @@ -13,8 +11,11 @@ use wasmer_types::WasmError; use wasmer_types::{ CompileError, DeserializeError, ExportsIterator, ImportsIterator, ModuleInfo, SerializeError, }; +use wasmer_types::{ExportType, ImportType}; use wasmer_vm::InstanceHandle; +use super::context::AsContextMut; + #[derive(Error, Debug)] pub enum IoCompileError { /// An IO error @@ -277,16 +278,24 @@ impl Module { pub(crate) fn instantiate( &self, + mut ctx: impl AsContextMut, imports: &[crate::Extern], ) -> Result { + // Ensure all imports come from the same context. + for import in imports { + if !import.is_from_context(ctx.as_context_ref()) { + return Err(InstantiationError::BadContext); + } + } + unsafe { - let instance_handle = self.artifact.instantiate( + let mut instance_handle = self.artifact.instantiate( self.store.tunables(), &imports .iter() - .map(crate::Extern::to_export) + .map(crate::Extern::to_vm_extern) .collect::>(), - Box::new(self.clone()), + ctx.as_context_mut().objects_mut(), )?; // After the instance handle is created, we need to initialize @@ -295,7 +304,7 @@ impl Module { // as some of the Instance elements may have placed in other // instance tables. self.artifact - .finish_instantiation(&self.store, &instance_handle)?; + .finish_instantiation(&self.store, &mut instance_handle)?; Ok(instance_handle) } diff --git a/lib/api/src/sys/native.rs b/lib/api/src/sys/native.rs index 8145f6d12b6..9024298940e 100644 --- a/lib/api/src/sys/native.rs +++ b/lib/api/src/sys/native.rs @@ -9,19 +9,16 @@ //! ``` use std::marker::PhantomData; -use crate::sys::externals::function::{DynamicFunction, VMDynamicFunction}; -use crate::sys::{FromToNativeWasmType, Function, RuntimeError, Store, WasmTypeList}; -use std::panic::{catch_unwind, AssertUnwindSafe}; -use wasmer_compiler::ExportFunction; -use wasmer_types::NativeWasmType; -use wasmer_vm::{VMDynamicFunctionContext, VMFunctionBody, VMFunctionEnvironment, VMFunctionKind}; +use crate::sys::{ + AsContextMut, FromToNativeWasmType, Function, NativeWasmTypeInto, RuntimeError, WasmTypeList, +}; +use wasmer_types::RawValue; /// A WebAssembly function that can be called natively /// (using the Native ABI). -pub struct TypedFunction { - store: Store, - exported: ExportFunction, - _phantom: PhantomData<(Args, Rets)>, +pub struct TypedFunction { + func: Function, + _phantom: PhantomData Rets>, } unsafe impl Send for TypedFunction {} @@ -31,95 +28,30 @@ where Args: WasmTypeList, Rets: WasmTypeList, { - pub(crate) fn new(store: Store, exported: ExportFunction) -> Self { + pub(crate) fn new(func: Function) -> Self { Self { - store, - exported, + func, _phantom: PhantomData, } } - - pub(crate) fn is_host(&self) -> bool { - self.exported.vm_function.instance_ref.is_none() - } - - pub(crate) fn vmctx(&self) -> VMFunctionEnvironment { - self.exported.vm_function.vmctx - } - - pub(crate) fn address(&self) -> *const VMFunctionBody { - self.exported.vm_function.address - } - - pub(crate) fn arg_kind(&self) -> VMFunctionKind { - self.exported.vm_function.kind - } - - /// Get access to the backing VM value for this extern. This function is for - /// tests it should not be called by users of the Wasmer API. - /// - /// # Safety - /// This function is unsafe to call outside of tests for the wasmer crate - /// because there is no stability guarantee for the returned type and we may - /// make breaking changes to it at any time or remove this method. - #[doc(hidden)] - pub unsafe fn get_vm_function(&self) -> &wasmer_vm::VMFunction { - &self.exported.vm_function - } } -/* -impl From<&TypedFunction> for VMFunction -where - Args: WasmTypeList, - Rets: WasmTypeList, -{ - fn from(other: &TypedFunction) -> Self { - let signature = FunctionType::new(Args::wasm_types(), Rets::wasm_types()); - Self { - address: other.address, - vmctx: other.vmctx, - signature, - kind: other.arg_kind, - call_trampoline: None, - instance_ref: None, - } - } -}*/ - impl Clone for TypedFunction { fn clone(&self) -> Self { - let mut exported = self.exported.clone(); - exported.vm_function.upgrade_instance_ref().unwrap(); - Self { - store: self.store.clone(), - exported, + func: self.func.clone(), _phantom: PhantomData, } } } -impl From<&TypedFunction> for ExportFunction -where - Args: WasmTypeList, - Rets: WasmTypeList, -{ - fn from(other: &TypedFunction) -> Self { - other.exported.clone() - } -} - impl From> for Function where Args: WasmTypeList, Rets: WasmTypeList, { fn from(other: TypedFunction) -> Self { - Self { - store: other.store, - exported: other.exported, - } + other.func } } @@ -132,110 +64,66 @@ macro_rules! impl_native_traits { Rets: WasmTypeList, { /// Call the typed func and return results. + #[allow(unused_mut)] #[allow(clippy::too_many_arguments)] - pub fn call(&self, $( $x: $x, )* ) -> Result { - if !self.is_host() { - // We assume the trampoline is always going to be present for - // Wasm functions - let trampoline = self.exported.vm_function.call_trampoline.expect("Call trampoline not found in wasm function"); - // TODO: when `const fn` related features mature more, we can declare a single array - // of the correct size here. - let mut params_list = [ $( $x.to_native().to_binary() ),* ]; - let mut rets_list_array = Rets::empty_array(); - let rets_list = rets_list_array.as_mut(); - let using_rets_array; - let args_rets: &mut [i128] = if params_list.len() > rets_list.len() { - using_rets_array = false; - params_list.as_mut() - } else { - using_rets_array = true; - for (i, &arg) in params_list.iter().enumerate() { - rets_list[i] = arg; - } - rets_list.as_mut() - }; - unsafe { - wasmer_vm::wasmer_call_trampoline( - &self.store, - self.vmctx(), - trampoline, - self.address(), - args_rets.as_mut_ptr() as *mut u8, - ) - }?; - let num_rets = rets_list.len(); - if !using_rets_array && num_rets > 0 { - let src_pointer = params_list.as_ptr(); - let rets_list = &mut rets_list_array.as_mut()[0] as *mut i128; - unsafe { - // TODO: we can probably remove this copy by doing some clever `transmute`s. - // we know it's not overlapping because `using_rets_array` is false - std::ptr::copy_nonoverlapping(src_pointer, - rets_list, - num_rets); - } + pub fn call(&self, mut ctx: impl AsContextMut, $( $x: $x, )* ) -> Result { + let anyfunc = unsafe { + *self.func + .handle + .get(ctx.as_context_ref().objects()) + .anyfunc + .as_ptr() + .as_ref() + }; + // TODO: when `const fn` related features mature more, we can declare a single array + // of the correct size here. + let mut params_list = [ $( $x.to_native().into_raw(ctx.as_context_mut()) ),* ]; + let mut rets_list_array = Rets::empty_array(); + let rets_list: &mut [RawValue] = rets_list_array.as_mut(); + let using_rets_array; + let args_rets: &mut [RawValue] = if params_list.len() > rets_list.len() { + using_rets_array = false; + params_list.as_mut() + } else { + using_rets_array = true; + for (i, &arg) in params_list.iter().enumerate() { + rets_list[i] = arg; } - Ok(Rets::from_array(rets_list_array)) - // TODO: When the Host ABI and Wasm ABI are the same, we could do this instead: - // but we can't currently detect whether that's safe. - // - // let results = unsafe { - // wasmer_vm::catch_traps_with_result(self.vmctx, || { - // let f = std::mem::transmute::<_, unsafe extern "C" fn( *mut VMContext, $( $x, )*) -> Rets::CStruct>(self.address()); - // // We always pass the vmctx - // f( self.vmctx, $( $x, )* ) - // }).map_err(RuntimeError::from_trap)? - // }; - // Ok(Rets::from_c_struct(results)) - - } - else { - match self.arg_kind() { - VMFunctionKind::Static => { - let results = catch_unwind(AssertUnwindSafe(|| unsafe { - let f = std::mem::transmute::<_, unsafe extern "C" fn( VMFunctionEnvironment, $( $x, )*) -> Rets::CStruct>(self.address()); - // We always pass the vmctx - f( self.vmctx(), $( $x, )* ) - })).map_err(|e| RuntimeError::new(format!("{:?}", e)))?; - Ok(Rets::from_c_struct(results)) - }, - VMFunctionKind::Dynamic => { - let params_list = [ $( $x.to_native().to_value() ),* ]; - let results = { - type VMContextWithEnv = VMDynamicFunctionContext>; - unsafe { - let ctx = self.vmctx().host_env as *mut VMContextWithEnv; - (*ctx).ctx.call(¶ms_list)? - } - }; - let mut rets_list_array = Rets::empty_array(); - let mut_rets = rets_list_array.as_mut() as *mut [i128] as *mut i128; - for (i, ret) in results.iter().enumerate() { - unsafe { - ret.write_value_to(mut_rets.add(i)); - } - } - Ok(Rets::from_array(rets_list_array)) - } + rets_list.as_mut() + }; + unsafe { + wasmer_vm::wasmer_call_trampoline( + ctx.as_context_ref().store(), + anyfunc.vmctx, + anyfunc.call_trampoline, + anyfunc.func_ptr, + args_rets.as_mut_ptr() as *mut u8, + ) + }?; + let num_rets = rets_list.len(); + if !using_rets_array && num_rets > 0 { + let src_pointer = params_list.as_ptr(); + let rets_list = &mut rets_list_array.as_mut()[0] as *mut RawValue; + unsafe { + // TODO: we can probably remove this copy by doing some clever `transmute`s. + // we know it's not overlapping because `using_rets_array` is false + std::ptr::copy_nonoverlapping(src_pointer, + rets_list, + num_rets); } } - } - - } - - #[allow(unused_parens)] - impl<'a, $( $x, )* Rets> crate::sys::exports::ExportableWithGenerics<'a, ($( $x ),*), Rets> for TypedFunction<( $( $x ),* ), Rets> - where - $( $x: FromToNativeWasmType, )* - Rets: WasmTypeList, - { - fn get_self_from_extern_with_generics(_extern: &crate::sys::externals::Extern) -> Result { - use crate::sys::exports::Exportable; - crate::Function::get_self_from_extern(_extern)?.native().map_err(|_| crate::sys::exports::ExportError::IncompatibleType) - } - - fn convert_to_weak_instance_ref(&mut self) { - self.exported.vm_function.instance_ref.as_mut().map(|v| *v = v.downgrade()); + Ok(unsafe { Rets::from_array(ctx, rets_list_array) }) + // TODO: When the Host ABI and Wasm ABI are the same, we could do this instead: + // but we can't currently detect whether that's safe. + // + // let results = unsafe { + // wasmer_vm::catch_traps_with_result(self.vmctx, || { + // let f = std::mem::transmute::<_, unsafe extern "C" fn( *mut VMContext, $( $x, )*) -> Rets::CStruct>(self.address()); + // // We always pass the vmctx + // f( self.vmctx, $( $x, )* ) + // }).map_err(RuntimeError::from_trap)? + // }; + // Ok(Rets::from_c_struct(results)) } } }; diff --git a/lib/api/src/sys/native_type.rs b/lib/api/src/sys/native_type.rs new file mode 100644 index 00000000000..edb978a7a0e --- /dev/null +++ b/lib/api/src/sys/native_type.rs @@ -0,0 +1,236 @@ +//! This module permits to create native functions +//! easily in Rust, thanks to its advanced typing system. + +use wasmer_types::{NativeWasmType, RawValue, Type}; +use wasmer_vm::{VMExternRef, VMFuncRef}; + +use crate::{ExternRef, Function}; + +use super::context::AsContextMut; + +/// `NativeWasmTypeInto` performs conversions from and into `NativeWasmType` +/// types with a context. +pub trait NativeWasmTypeInto: NativeWasmType + Sized { + #[doc(hidden)] + fn into_abi(self, ctx: impl AsContextMut) -> Self::Abi; + + #[doc(hidden)] + unsafe fn from_abi(ctx: impl AsContextMut, abi: Self::Abi) -> Self; + + /// Convert self to raw value representation. + fn into_raw(self, ctx: impl AsContextMut) -> RawValue; + + /// Convert to self from raw value representation. + /// + /// # Safety + /// + unsafe fn from_raw(ctx: impl AsContextMut, raw: RawValue) -> Self; +} + +impl NativeWasmTypeInto for i32 { + #[inline] + unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + RawValue { i32: self } + } + + #[inline] + unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + raw.i32 + } +} + +impl NativeWasmTypeInto for i64 { + #[inline] + unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + RawValue { i64: self } + } + + #[inline] + unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + raw.i64 + } +} + +impl NativeWasmTypeInto for f32 { + #[inline] + unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + RawValue { f32: self } + } + + #[inline] + unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + raw.f32 + } +} + +impl NativeWasmTypeInto for f64 { + #[inline] + unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + RawValue { f64: self } + } + + #[inline] + unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + raw.f64 + } +} + +impl NativeWasmTypeInto for u128 { + #[inline] + unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + RawValue { u128: self } + } + + #[inline] + unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + raw.u128 + } +} + +impl NativeWasmType for ExternRef { + const WASM_TYPE: Type = Type::ExternRef; + type Abi = usize; +} + +impl NativeWasmTypeInto for Option { + #[inline] + unsafe fn from_abi(ctx: impl AsContextMut, abi: Self::Abi) -> Self { + VMExternRef::from_raw(RawValue { externref: abi }) + .map(|e| ExternRef::from_vm_externref(ctx, e)) + } + + #[inline] + fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + self.map_or(0, |e| unsafe { e.vm_externref().into_raw().externref }) + } + + #[inline] + fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + self.map_or(RawValue { externref: 0 }, |e| e.vm_externref().into_raw()) + } + + #[inline] + unsafe fn from_raw(ctx: impl AsContextMut, raw: RawValue) -> Self { + VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(ctx, e)) + } +} + +impl NativeWasmType for Function { + const WASM_TYPE: Type = Type::FuncRef; + type Abi = usize; +} + +impl NativeWasmTypeInto for Option { + #[inline] + unsafe fn from_abi(ctx: impl AsContextMut, abi: Self::Abi) -> Self { + VMFuncRef::from_raw(RawValue { funcref: abi }).map(|f| Function::from_vm_funcref(ctx, f)) + } + + #[inline] + fn into_abi(self, ctx: impl AsContextMut) -> Self::Abi { + self.map_or(0, |f| unsafe { f.vm_funcref(ctx).into_raw().externref }) + } + + #[inline] + fn into_raw(self, ctx: impl AsContextMut) -> RawValue { + self.map_or(RawValue { externref: 0 }, |e| e.vm_funcref(ctx).into_raw()) + } + + #[inline] + unsafe fn from_raw(ctx: impl AsContextMut, raw: RawValue) -> Self { + VMFuncRef::from_raw(raw).map(|f| Function::from_vm_funcref(ctx, f)) + } +} + +#[cfg(test)] +mod test_native_type { + use super::*; + use wasmer_types::Type; + + #[test] + fn test_wasm_types() { + assert_eq!(i32::WASM_TYPE, Type::I32); + assert_eq!(i64::WASM_TYPE, Type::I64); + assert_eq!(f32::WASM_TYPE, Type::F32); + assert_eq!(f64::WASM_TYPE, Type::F64); + assert_eq!(u128::WASM_TYPE, Type::V128); + } + + #[test] + fn test_roundtrip() { + unsafe { + assert_eq!(i32::from_raw(42i32.into_raw()), 42i32); + assert_eq!(i64::from_raw(42i64.into_raw()), 42i64); + assert_eq!(f32::from_raw(42f32.into_raw()), 42f32); + assert_eq!(f64::from_raw(42f64.into_raw()), 42f64); + assert_eq!(u128::from_raw(42u128.into_raw()), 42u128); + } + } +} + +// pub trait IntegerAtomic +// where +// Self: Sized +// { +// type Primitive; + +// fn add(&self, other: Self::Primitive) -> Self::Primitive; +// fn sub(&self, other: Self::Primitive) -> Self::Primitive; +// fn and(&self, other: Self::Primitive) -> Self::Primitive; +// fn or(&self, other: Self::Primitive) -> Self::Primitive; +// fn xor(&self, other: Self::Primitive) -> Self::Primitive; +// fn load(&self) -> Self::Primitive; +// fn store(&self, other: Self::Primitive) -> Self::Primitive; +// fn compare_exchange(&self, expected: Self::Primitive, new: Self::Primitive) -> Self::Primitive; +// fn swap(&self, other: Self::Primitive) -> Self::Primitive; +// } diff --git a/lib/api/src/sys/ptr.rs b/lib/api/src/sys/ptr.rs index 3ece04f551e..158cfc44a25 100644 --- a/lib/api/src/sys/ptr.rs +++ b/lib/api/src/sys/ptr.rs @@ -1,9 +1,12 @@ use crate::sys::{externals::Memory, FromToNativeWasmType}; +use crate::NativeWasmTypeInto; use crate::{MemoryAccessError, WasmRef, WasmSlice}; use std::convert::TryFrom; use std::{fmt, marker::PhantomData, mem}; use wasmer_types::ValueType; +use super::context::AsContextRef; + pub use wasmer_types::MemorySize; pub use wasmer_types::Memory32; @@ -139,20 +142,25 @@ impl WasmPtr { /// Creates a `WasmRef` from this `WasmPtr` which allows reading and /// mutating of the value being pointed to. #[inline] - pub fn deref(self, memory: &Memory) -> WasmRef<'_, T> { - WasmRef::new(memory, self.offset.into()) + pub fn deref<'a>(self, ctx: &'a impl AsContextRef, memory: &'a Memory) -> WasmRef<'a, T> { + WasmRef::new(ctx, memory, self.offset.into()) } /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, memory: &Memory) -> Result { - self.deref(memory).read() + pub fn read(self, ctx: impl AsContextRef, memory: &Memory) -> Result { + self.deref(&ctx, memory).read() } /// Writes to the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn write(self, memory: &Memory, val: T) -> Result<(), MemoryAccessError> { - self.deref(memory).write(val) + pub fn write( + self, + ctx: impl AsContextRef, + memory: &Memory, + val: T, + ) -> Result<(), MemoryAccessError> { + self.deref(&ctx, memory).write(val) } /// Creates a `WasmSlice` starting at this `WasmPtr` which allows reading @@ -161,12 +169,13 @@ impl WasmPtr { /// Returns a `MemoryAccessError` if the slice length overflows a 64-bit /// address. #[inline] - pub fn slice( + pub fn slice<'a>( self, - memory: &Memory, + ctx: &'a impl AsContextRef, + memory: &'a Memory, len: M::Offset, - ) -> Result, MemoryAccessError> { - WasmSlice::new(memory, self.offset.into(), len.into()) + ) -> Result, MemoryAccessError> { + WasmSlice::new(ctx, memory, self.offset.into(), len.into()) } /// Reads a sequence of values from this `WasmPtr` until a value that @@ -176,13 +185,14 @@ impl WasmPtr { #[inline] pub fn read_until( self, + ctx: impl AsContextRef, memory: &Memory, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { let mut vec = Vec::new(); for i in 0u64.. { let i = M::Offset::try_from(i).map_err(|_| MemoryAccessError::Overflow)?; - let val = self.add_offset(i)?.deref(memory).read()?; + let val = self.add_offset(i)?.deref(&ctx, memory).read()?; if end(&val) { break; } @@ -200,10 +210,11 @@ impl WasmPtr { #[inline] pub fn read_utf8_string( self, + ctx: impl AsContextRef, memory: &Memory, len: M::Offset, ) -> Result { - let vec = self.slice(memory, len)?.read_to_vec()?; + let vec = self.slice(&ctx, memory, len)?.read_to_vec()?; Ok(String::from_utf8(vec)?) } @@ -212,13 +223,20 @@ impl WasmPtr { /// This method is safe to call even if the memory is being concurrently /// modified. #[inline] - pub fn read_utf8_string_with_nul(self, memory: &Memory) -> Result { - let vec = self.read_until(memory, |&byte| byte == 0)?; + pub fn read_utf8_string_with_nul( + self, + ctx: impl AsContextRef, + memory: &Memory, + ) -> Result { + let vec = self.read_until(ctx, memory, |&byte| byte == 0)?; Ok(String::from_utf8(vec)?) } } -unsafe impl FromToNativeWasmType for WasmPtr { +unsafe impl FromToNativeWasmType for WasmPtr +where + ::Native: NativeWasmTypeInto, +{ type Native = M::Native; fn to_native(self) -> Self::Native { diff --git a/lib/api/src/sys/store.rs b/lib/api/src/sys/store.rs index b779587fbf1..ad8c2bce2c7 100644 --- a/lib/api/src/sys/store.rs +++ b/lib/api/src/sys/store.rs @@ -144,9 +144,3 @@ impl fmt::Debug for Store { f.debug_struct("Store").finish() } } - -/// A trait represinting any object that lives in the `Store`. -pub trait StoreObject { - /// Return true if the object `Store` is the same as the provided `Store`. - fn comes_from_same_store(&self, store: &Store) -> bool; -} diff --git a/lib/api/src/sys/tunables.rs b/lib/api/src/sys/tunables.rs index 98e82546985..aeaa4fb6692 100644 --- a/lib/api/src/sys/tunables.rs +++ b/lib/api/src/sys/tunables.rs @@ -1,12 +1,10 @@ use crate::sys::{MemoryType, Pages, TableType}; use std::ptr::NonNull; -use std::sync::Arc; use target_lexicon::PointerWidth; use wasmer_compiler::{Target, Tunables}; use wasmer_vm::MemoryError; use wasmer_vm::{ - LinearMemory, LinearTable, Memory, MemoryStyle, Table, TableStyle, VMMemoryDefinition, - VMTableDefinition, + MemoryStyle, TableStyle, VMMemory, VMMemoryDefinition, VMTable, VMTableDefinition, }; /// Tunable parameters for WebAssembly compilation. @@ -96,8 +94,8 @@ impl Tunables for BaseTunables { &self, ty: &MemoryType, style: &MemoryStyle, - ) -> Result, MemoryError> { - Ok(Arc::new(LinearMemory::new(ty, style)?)) + ) -> Result { + VMMemory::new(ty, style) } /// Create a memory owned by the VM given a [`MemoryType`] and a [`MemoryStyle`]. @@ -110,21 +108,13 @@ impl Tunables for BaseTunables { ty: &MemoryType, style: &MemoryStyle, vm_definition_location: NonNull, - ) -> Result, MemoryError> { - Ok(Arc::new(LinearMemory::from_definition( - ty, - style, - vm_definition_location, - )?)) + ) -> Result { + VMMemory::from_definition(ty, style, vm_definition_location) } /// Create a table owned by the host given a [`TableType`] and a [`TableStyle`]. - fn create_host_table( - &self, - ty: &TableType, - style: &TableStyle, - ) -> Result, String> { - Ok(Arc::new(LinearTable::new(ty, style)?)) + fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result { + VMTable::new(ty, style) } /// Create a table owned by the VM given a [`TableType`] and a [`TableStyle`]. @@ -137,12 +127,8 @@ impl Tunables for BaseTunables { ty: &TableType, style: &TableStyle, vm_definition_location: NonNull, - ) -> Result, String> { - Ok(Arc::new(LinearTable::from_definition( - ty, - style, - vm_definition_location, - )?)) + ) -> Result { + VMTable::from_definition(ty, style, vm_definition_location) } } diff --git a/lib/api/src/sys/types.rs b/lib/api/src/sys/types.rs deleted file mode 100644 index 7de09ffc57a..00000000000 --- a/lib/api/src/sys/types.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::sys::externals::Function; -use crate::sys::store::{Store, StoreObject}; -use crate::sys::RuntimeError; -use wasmer_types::Value; -pub use wasmer_types::{ - ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, - TableType, Type as ValType, -}; -use wasmer_vm::VMFuncRef; - -/// WebAssembly computations manipulate values of basic value types: -/// * Integers (32 or 64 bit width) -/// * Floating-point (32 or 64 bit width) -/// * Vectors (128 bits, with 32 or 64 bit lanes) -/// -/// Spec: -pub type Val = Value; - -impl StoreObject for Val { - fn comes_from_same_store(&self, store: &Store) -> bool { - match self { - Self::FuncRef(None) => true, - Self::FuncRef(Some(f)) => Store::same(store, f.store()), - // `ExternRef`s are not tied to specific stores - Self::ExternRef(_) => true, - Self::I32(_) | Self::I64(_) | Self::F32(_) | Self::F64(_) | Self::V128(_) => true, - } - } -} - -impl From for Val { - fn from(val: Function) -> Self { - Self::FuncRef(Some(val)) - } -} - -/// It provides useful functions for converting back and forth -/// from [`Val`] into `FuncRef`. -pub trait ValFuncRef { - fn into_vm_funcref(self, store: &Store) -> Result; - - fn from_vm_funcref(item: VMFuncRef, store: &Store) -> Self; - - fn into_table_reference(self, store: &Store) -> Result; - - fn from_table_reference(item: wasmer_vm::TableElement, store: &Store) -> Self; -} - -impl ValFuncRef for Val { - fn into_vm_funcref(self, store: &Store) -> Result { - if !self.comes_from_same_store(store) { - return Err(RuntimeError::new("cross-`Store` values are not supported")); - } - Ok(match self { - Self::FuncRef(None) => VMFuncRef::null(), - Self::FuncRef(Some(f)) => f.vm_funcref(), - _ => return Err(RuntimeError::new("val is not func ref")), - }) - } - - fn from_vm_funcref(func_ref: VMFuncRef, store: &Store) -> Self { - if func_ref.is_null() { - return Self::FuncRef(None); - } - let item: &wasmer_vm::VMCallerCheckedAnyfunc = unsafe { - let anyfunc: *const wasmer_vm::VMCallerCheckedAnyfunc = *func_ref; - &*anyfunc - }; - let signature = store - .engine() - .lookup_signature(item.type_index) - .expect("Signature not found in store"); - let export = wasmer_compiler::ExportFunction { - // TODO: - // figure out if we ever need a value here: need testing with complicated import patterns - metadata: None, - vm_function: wasmer_vm::VMFunction { - address: item.func_ptr, - signature, - // TODO: review this comment (unclear if it's still correct): - // All functions in tables are already Static (as dynamic functions - // are converted to use the trampolines with static signatures). - kind: wasmer_vm::VMFunctionKind::Static, - vmctx: item.vmctx, - call_trampoline: None, - instance_ref: None, - }, - }; - let f = Function::from_vm_export(store, export); - Self::FuncRef(Some(f)) - } - - fn into_table_reference(self, store: &Store) -> Result { - if !self.comes_from_same_store(store) { - return Err(RuntimeError::new("cross-`Store` values are not supported")); - } - Ok(match self { - // TODO(reftypes): review this clone - Self::ExternRef(extern_ref) => wasmer_vm::TableElement::ExternRef(extern_ref), - Self::FuncRef(None) => wasmer_vm::TableElement::FuncRef(VMFuncRef::null()), - Self::FuncRef(Some(f)) => wasmer_vm::TableElement::FuncRef(f.vm_funcref()), - _ => return Err(RuntimeError::new("val is not reference")), - }) - } - - fn from_table_reference(item: wasmer_vm::TableElement, store: &Store) -> Self { - match item { - wasmer_vm::TableElement::FuncRef(f) => Self::from_vm_funcref(f, store), - wasmer_vm::TableElement::ExternRef(extern_ref) => Self::ExternRef(extern_ref), - } - } -} diff --git a/lib/types/src/values.rs b/lib/api/src/sys/value.rs similarity index 64% rename from lib/types/src/values.rs rename to lib/api/src/sys/value.rs index ada2ab16935..49974035c37 100644 --- a/lib/types/src/values.rs +++ b/lib/api/src/sys/value.rs @@ -1,14 +1,27 @@ -use crate::extern_ref::ExternRef; -use crate::lib::std::convert::TryFrom; -use crate::lib::std::fmt; -use crate::lib::std::ptr; -use crate::lib::std::string::{String, ToString}; -use crate::types::Type; - -/// Possible runtime values that a WebAssembly module can either consume or -/// produce. -#[derive(Clone, PartialEq)] -pub enum Value { +use std::convert::TryFrom; +use std::fmt; +use std::string::{String, ToString}; + +use wasmer_types::Type; +use wasmer_vm::VMExternRef; +use wasmer_vm::VMFuncRef; + +use crate::ExternRef; +use crate::Function; + +use super::context::AsContextMut; +use super::context::AsContextRef; + +pub use wasmer_types::RawValue; + +/// WebAssembly computations manipulate values of basic value types: +/// * Integers (32 or 64 bit width) +/// * Floating-point (32 or 64 bit width) +/// * Vectors (128 bits, with 32 or 64 bit lanes) +/// +/// Spec: +#[derive(Clone)] +pub enum Value { /// A 32-bit integer. /// /// In Wasm integers are sign-agnostic, i.e. this can either be signed or unsigned. @@ -26,12 +39,10 @@ pub enum Value { F64(f64), /// An `externref` value which can hold opaque data to the wasm instance itself. - /// - /// Note that this is a nullable value as well. - ExternRef(ExternRef), + ExternRef(Option), /// A first-class reference to a WebAssembly function. - FuncRef(Option), + FuncRef(Option), /// A 128-bit number V128(u128), @@ -61,40 +72,10 @@ macro_rules! accessors { )*) } -/// Trait for reading and writing Wasm values into binary for use on the layer -/// between the API and the VM internals, specifically with `wasmer_types::Value`. -pub trait WasmValueType: std::fmt::Debug + 'static { - /// Write the value - /// - /// # Safety - /// You shouldn't use this method directly as it writes the value to a mutable pointer. - unsafe fn write_value_to(&self, p: *mut i128); - - /// read the value - /// - /// # Safety - /// It reads the value directly from a memory pointer, you need to make sure is not corrupted - // - // TODO(reftypes): passing the store as `dyn Any` is a hack to work around the - // structure of our crates. We need to talk about the store in the rest of the - // VM (for example where this method is used) but cannot do so. Fixing this - // may be non-trivial. - unsafe fn read_value_from(store: &dyn std::any::Any, p: *const i128) -> Self; -} - -impl WasmValueType for () { - unsafe fn write_value_to(&self, _p: *mut i128) {} - - unsafe fn read_value_from(_store: &dyn std::any::Any, _p: *const i128) -> Self {} -} - -impl Value -where - T: WasmValueType, -{ +impl Value { /// Returns a null `externref` value. pub fn null() -> Self { - Self::ExternRef(ExternRef::null()) + Self::ExternRef(None) } /// Returns the corresponding [`Type`] for this `Value`. @@ -110,51 +91,60 @@ where } } - /// Writes it's value to a given pointer - /// - /// # Safety - /// `p` must be: - /// - Sufficiently aligned for the Rust equivalent of the type in `self` - /// - Non-null and pointing to valid, mutable memory - pub unsafe fn write_value_to(&self, p: *mut i128) { - match self { - Self::I32(i) => ptr::write(p as *mut i32, *i), - Self::I64(i) => ptr::write(p as *mut i64, *i), - Self::F32(u) => ptr::write(p as *mut f32, *u), - Self::F64(u) => ptr::write(p as *mut f64, *u), - Self::V128(b) => ptr::write(p as *mut u128, *b), - Self::FuncRef(Some(b)) => T::write_value_to(b, p), - Self::FuncRef(None) => ptr::write(p as *mut usize, 0), - // TODO(reftypes): review clone here - Self::ExternRef(extern_ref) => ptr::write(p as *mut ExternRef, extern_ref.clone()), + /// Converts the `Value` into a `RawValue`. + pub fn as_raw(&self, ctx: impl AsContextRef) -> RawValue { + match *self { + Self::I32(i32) => RawValue { i32 }, + Self::I64(i64) => RawValue { i64 }, + Self::F32(f32) => RawValue { f32 }, + Self::F64(f64) => RawValue { f64 }, + Self::V128(u128) => RawValue { u128 }, + Self::FuncRef(Some(ref f)) => f.vm_funcref(ctx).into_raw(), + + Self::FuncRef(None) => RawValue { funcref: 0 }, + Self::ExternRef(Some(ref e)) => e.vm_externref().into_raw(), + Self::ExternRef(None) => RawValue { externref: 0 }, } } - /// Gets a `Value` given a pointer and a `Type` + /// Converts a `RawValue` to a `Value`. /// /// # Safety - /// `p` must be: - /// - Properly aligned to the specified `ty`'s Rust equivalent - /// - Non-null and pointing to valid memory - pub unsafe fn read_value_from(store: &dyn std::any::Any, p: *const i128, ty: Type) -> Self { + /// + pub unsafe fn from_raw(ctx: impl AsContextMut, ty: Type, raw: RawValue) -> Self { match ty { - Type::I32 => Self::I32(ptr::read(p as *const i32)), - Type::I64 => Self::I64(ptr::read(p as *const i64)), - Type::F32 => Self::F32(ptr::read(p as *const f32)), - Type::F64 => Self::F64(ptr::read(p as *const f64)), - Type::V128 => Self::V128(ptr::read(p as *const u128)), + Type::I32 => Self::I32(raw.i32), + Type::I64 => Self::I64(raw.i64), + Type::F32 => Self::F32(raw.f32), + Type::F64 => Self::F64(raw.f64), + Type::V128 => Self::V128(raw.u128), Type::FuncRef => { - // We do the null check ourselves - if (*(p as *const usize)) == 0 { - Self::FuncRef(None) - } else { - Self::FuncRef(Some(T::read_value_from(store, p))) - } - } - Type::ExternRef => { - let extern_ref = (&*(p as *const ExternRef)).clone(); - Self::ExternRef(extern_ref) + Self::FuncRef(VMFuncRef::from_raw(raw).map(|f| Function::from_vm_funcref(ctx, f))) } + Type::ExternRef => Self::ExternRef( + VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(ctx, e)), + ), + } + } + + /// Checks whether a value can be used with the given context. + /// + /// Primitive (`i32`, `i64`, etc) and null funcref/externref values are not + /// tied to a context and can be freely shared between contexts. + /// + /// Externref and funcref values are tied to a context and can only be used + /// with that context. + pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + match self { + Self::I32(_) + | Self::I64(_) + | Self::F32(_) + | Self::F64(_) + | Self::V128(_) + | Self::ExternRef(None) + | Self::FuncRef(None) => true, + Self::ExternRef(Some(e)) => e.is_from_context(ctx), + Self::FuncRef(Some(f)) => f.is_from_context(ctx), } } @@ -164,23 +154,21 @@ where (I64(i64) i64 unwrap_i64 *e) (F32(f32) f32 unwrap_f32 *e) (F64(f64) f64 unwrap_f64 *e) - (ExternRef(ExternRef) externref unwrap_externref e.clone()) - (FuncRef(&Option) funcref unwrap_funcref e) + (ExternRef(&Option) externref unwrap_externref e) + (FuncRef(&Option) funcref unwrap_funcref e) (V128(u128) v128 unwrap_v128 *e) } } -impl fmt::Debug for Value -where - T: WasmValueType, -{ +impl fmt::Debug for Value { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::I32(v) => write!(f, "I32({:?})", v), Self::I64(v) => write!(f, "I64({:?})", v), Self::F32(v) => write!(f, "F32({:?})", v), Self::F64(v) => write!(f, "F64({:?})", v), - Self::ExternRef(v) => write!(f, "ExternRef({:?})", v), + Self::ExternRef(None) => write!(f, "Null ExternRef"), + Self::ExternRef(Some(v)) => write!(f, "ExternRef({:?})", v), Self::FuncRef(None) => write!(f, "Null FuncRef"), Self::FuncRef(Some(v)) => write!(f, "FuncRef({:?})", v), Self::V128(v) => write!(f, "V128({:?})", v), @@ -188,10 +176,7 @@ where } } -impl ToString for Value -where - T: WasmValueType, -{ +impl ToString for Value { fn to_string(&self) -> String { match self { Self::I32(v) => v.to_string(), @@ -205,148 +190,145 @@ where } } -impl From for Value -where - T: WasmValueType, -{ +impl From for Value { fn from(val: i32) -> Self { Self::I32(val) } } -impl From for Value -where - T: WasmValueType, -{ +impl From for Value { fn from(val: u32) -> Self { // In Wasm integers are sign-agnostic, so i32 is basically a 4 byte storage we can use for signed or unsigned 32-bit integers. Self::I32(val as i32) } } -impl From for Value -where - T: WasmValueType, -{ +impl From for Value { fn from(val: i64) -> Self { Self::I64(val) } } -impl From for Value -where - T: WasmValueType, -{ +impl From for Value { fn from(val: u64) -> Self { // In Wasm integers are sign-agnostic, so i64 is basically an 8 byte storage we can use for signed or unsigned 64-bit integers. Self::I64(val as i64) } } -impl From for Value -where - T: WasmValueType, -{ +impl From for Value { fn from(val: f32) -> Self { Self::F32(val) } } -impl From for Value -where - T: WasmValueType, -{ +impl From for Value { fn from(val: f64) -> Self { Self::F64(val) } } -impl From for Value -where - T: WasmValueType, -{ +impl From for Value { + fn from(val: Function) -> Self { + Self::FuncRef(Some(val)) + } +} + +impl From> for Value { + fn from(val: Option) -> Self { + Self::FuncRef(val) + } +} + +impl From for Value { fn from(val: ExternRef) -> Self { - Self::ExternRef(val) + Self::ExternRef(Some(val)) } } -// impl From for Value { -// fn from(val: T) -> Self { -// Self::FuncRef(val) -// } -// } +impl From> for Value { + fn from(val: Option) -> Self { + Self::ExternRef(val) + } +} const NOT_I32: &str = "Value is not of Wasm type i32"; const NOT_I64: &str = "Value is not of Wasm type i64"; const NOT_F32: &str = "Value is not of Wasm type f32"; const NOT_F64: &str = "Value is not of Wasm type f64"; +const NOT_FUNCREF: &str = "Value is not of Wasm type funcref"; +const NOT_EXTERNREF: &str = "Value is not of Wasm type externref"; -impl TryFrom> for i32 -where - T: WasmValueType, -{ +impl TryFrom for i32 { type Error = &'static str; - fn try_from(value: Value) -> Result { + fn try_from(value: Value) -> Result { value.i32().ok_or(NOT_I32) } } -impl TryFrom> for u32 -where - T: WasmValueType, -{ +impl TryFrom for u32 { type Error = &'static str; - fn try_from(value: Value) -> Result { + fn try_from(value: Value) -> Result { value.i32().ok_or(NOT_I32).map(|int| int as Self) } } -impl TryFrom> for i64 -where - T: WasmValueType, -{ +impl TryFrom for i64 { type Error = &'static str; - fn try_from(value: Value) -> Result { + fn try_from(value: Value) -> Result { value.i64().ok_or(NOT_I64) } } -impl TryFrom> for u64 -where - T: WasmValueType, -{ +impl TryFrom for u64 { type Error = &'static str; - fn try_from(value: Value) -> Result { + fn try_from(value: Value) -> Result { value.i64().ok_or(NOT_I64).map(|int| int as Self) } } -impl TryFrom> for f32 -where - T: WasmValueType, -{ +impl TryFrom for f32 { type Error = &'static str; - fn try_from(value: Value) -> Result { + fn try_from(value: Value) -> Result { value.f32().ok_or(NOT_F32) } } -impl TryFrom> for f64 -where - T: WasmValueType, -{ +impl TryFrom for f64 { type Error = &'static str; - fn try_from(value: Value) -> Result { + fn try_from(value: Value) -> Result { value.f64().ok_or(NOT_F64) } } +impl TryFrom for Option { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + match value { + Value::FuncRef(f) => Ok(f), + _ => Err(NOT_FUNCREF), + } + } +} + +impl TryFrom for Option { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + match value { + Value::ExternRef(e) => Ok(e), + _ => Err(NOT_EXTERNREF), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs index 31e511c2b4a..bc424b47265 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/sys_reference_types.rs @@ -124,7 +124,6 @@ mod sys { Ok(()) } - #[cfg(feature = "experimental-reference-types-extern-ref")] #[test] fn extern_ref_passed_and_returned() -> Result<()> { let store = Store::default(); @@ -212,7 +211,6 @@ mod sys { Ok(()) } - #[cfg(feature = "experimental-reference-types-extern-ref")] #[test] // TODO(reftypes): reenable this test #[ignore] @@ -235,7 +233,6 @@ mod sys { Ok(()) } - #[cfg(feature = "experimental-reference-types-extern-ref")] #[test] fn refs_in_globals() -> Result<()> { let store = Store::default(); @@ -301,7 +298,6 @@ mod sys { Ok(()) } - #[cfg(feature = "experimental-reference-types-extern-ref")] #[test] fn extern_ref_ref_counting_table_basic() -> Result<()> { let store = Store::default(); @@ -342,7 +338,6 @@ mod sys { Ok(()) } - #[cfg(feature = "experimental-reference-types-extern-ref")] #[test] // TODO(reftypes): reenable this test #[ignore] @@ -374,7 +369,6 @@ mod sys { Ok(()) } - #[cfg(feature = "experimental-reference-types-extern-ref")] #[test] // TODO(reftypes): reenable this test #[ignore] @@ -401,7 +395,6 @@ mod sys { Ok(()) } - #[cfg(feature = "experimental-reference-types-extern-ref")] #[test] fn extern_ref_ref_counting_table_instructions() -> Result<()> { let store = Store::default(); diff --git a/lib/c-api/src/wasm_c_api/unstable/wasi.rs b/lib/c-api/src/wasm_c_api/unstable/wasi.rs index f2d1b944713..b3832669f55 100644 --- a/lib/c-api/src/wasm_c_api/unstable/wasi.rs +++ b/lib/c-api/src/wasm_c_api/unstable/wasi.rs @@ -178,7 +178,7 @@ fn wasi_get_unordered_imports_inner( .map(|((module, name), extern_)| { let module = module.into(); let name = name.into(); - let extern_inner = Extern::from_vm_export(store, extern_.to_export()); + let extern_inner = Extern::from_vm_export(store, extern_.to_vm_extern()); Some(Box::new(wasmer_named_extern_t { module, diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index a285c916c02..3daacd8e70e 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -358,7 +358,7 @@ fn wasi_get_imports_inner( import_type.name() ) })?; - let inner = Extern::from_vm_export(store, ext.to_export()); + let inner = Extern::from_vm_export(store, ext.to_vm_extern()); Ok(Some(Box::new(inner.into()))) }) diff --git a/lib/compiler/src/engine/artifact.rs b/lib/compiler/src/engine/artifact.rs index 158247979f7..00d3924f585 100644 --- a/lib/compiler/src/engine/artifact.rs +++ b/lib/compiler/src/engine/artifact.rs @@ -1,11 +1,10 @@ use crate::CpuFeature; -use crate::{resolve_imports, Export, InstantiationError, RuntimeError, Tunables}; +use crate::{resolve_imports, InstantiationError, RuntimeError, Tunables}; use crate::{ArtifactCreate, Upcastable}; -use std::any::Any; use wasmer_types::entity::BoxedSlice; use wasmer_types::{DataInitializer, FunctionIndex, LocalFunctionIndex, SignatureIndex}; use wasmer_vm::{ - FuncDataRegistry, FunctionBodyPtr, InstanceAllocator, InstanceHandle, TrapHandler, + ContextObjects, FunctionBodyPtr, InstanceAllocator, InstanceHandle, TrapHandler, VMExtern, VMSharedSignatureIndex, VMTrampoline, }; @@ -39,9 +38,6 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { /// Returns the associated VM signatures for this `Artifact`. fn signatures(&self) -> &BoxedSlice; - /// Get the func data registry - fn func_data_registry(&self) -> &FuncDataRegistry; - /// Do preinstantiation logic that is executed before instantiating fn preinstantiate(&self) -> Result<(), InstantiationError> { Ok(()) @@ -54,8 +50,8 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { unsafe fn instantiate( &self, tunables: &dyn Tunables, - imports: &[Export], - host_state: Box, + imports: &[VMExtern], + context: &mut ContextObjects, ) -> Result { // Validate the CPU features this module was compiled with against the // host CPU features. @@ -70,22 +66,15 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { self.preinstantiate()?; let module = self.module(); - let (imports, import_function_envs) = { - let mut imports = resolve_imports( - &module, - imports, - self.finished_dynamic_function_trampolines(), - self.memory_styles(), - self.table_styles(), - ) - .map_err(InstantiationError::Link)?; - - // Get the `WasmerEnv::init_with_instance` function pointers and the pointers - // to the envs to call it on. - let import_function_envs = imports.get_imported_function_envs(); - - (imports, import_function_envs) - }; + let imports = resolve_imports( + &module, + imports, + context, + self.finished_dynamic_function_trampolines(), + self.memory_styles(), + self.table_styles(), + ) + .map_err(InstantiationError::Link)?; // Get pointers to where metadata about local memories should live in VM memory. // Get pointers to where metadata about local tables should live in VM memory. @@ -93,15 +82,25 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { let (allocator, memory_definition_locations, table_definition_locations) = InstanceAllocator::new(&*module); let finished_memories = tunables - .create_memories(&module, self.memory_styles(), &memory_definition_locations) + .create_memories( + context, + &module, + self.memory_styles(), + &memory_definition_locations, + ) .map_err(InstantiationError::Link)? .into_boxed_slice(); let finished_tables = tunables - .create_tables(&module, self.table_styles(), &table_definition_locations) + .create_tables( + context, + &module, + self.table_styles(), + &table_definition_locations, + ) .map_err(InstantiationError::Link)? .into_boxed_slice(); let finished_globals = tunables - .create_globals(&module) + .create_globals(context, &module) .map_err(InstantiationError::Link)? .into_boxed_slice(); @@ -110,6 +109,7 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { let handle = InstanceHandle::new( allocator, module, + context, self.finished_functions().clone(), self.finished_function_call_trampolines().clone(), finished_memories, @@ -117,8 +117,6 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { finished_globals, imports, self.signatures().clone(), - host_state, - import_function_envs, ) .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?; Ok(handle) @@ -131,7 +129,7 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { unsafe fn finish_instantiation( &self, trap_handler: &(dyn TrapHandler + 'static), - handle: &InstanceHandle, + handle: &mut InstanceHandle, ) -> Result<(), InstantiationError> { let data_initializers = self .data_initializers() diff --git a/lib/compiler/src/engine/inner.rs b/lib/compiler/src/engine/inner.rs index 7b5772ad038..eba7006d3cc 100644 --- a/lib/compiler/src/engine/inner.rs +++ b/lib/compiler/src/engine/inner.rs @@ -8,7 +8,7 @@ use std::path::Path; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use std::sync::Arc; use wasmer_types::{CompileError, DeserializeError, FunctionType}; -use wasmer_vm::{VMCallerCheckedAnyfunc, VMFuncRef, VMSharedSignatureIndex}; +use wasmer_vm::VMSharedSignatureIndex; /// A unimplemented Wasmer `Engine`. /// @@ -23,9 +23,6 @@ pub trait Engine { /// Register a signature fn register_signature(&self, func_type: &FunctionType) -> VMSharedSignatureIndex; - /// Register a function's data. - fn register_function_metadata(&self, func_data: VMCallerCheckedAnyfunc) -> VMFuncRef; - /// Lookup a signature fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option; diff --git a/lib/compiler/src/engine/mod.rs b/lib/compiler/src/engine/mod.rs index d01881fb203..4ad5cef789b 100644 --- a/lib/compiler/src/engine/mod.rs +++ b/lib/compiler/src/engine/mod.rs @@ -2,7 +2,6 @@ mod artifact; mod error; -mod export; mod inner; mod resolver; mod trap; @@ -13,7 +12,6 @@ mod universal; pub use self::artifact::Artifact; pub use self::error::{InstantiationError, LinkError}; -pub use self::export::{Export, ExportFunction, ExportFunctionMetadata}; pub use self::inner::{Engine, EngineId}; pub use self::resolver::resolve_imports; pub use self::trap::*; diff --git a/lib/compiler/src/engine/resolver.rs b/lib/compiler/src/engine/resolver.rs index 3e8c1656e3a..3835766aa19 100644 --- a/lib/compiler/src/engine/resolver.rs +++ b/lib/compiler/src/engine/resolver.rs @@ -1,6 +1,6 @@ //! Custom resolution for external references. -use crate::{Export, ExportFunctionMetadata, LinkError}; +use crate::LinkError; use more_asserts::assert_ge; use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap}; use wasmer_types::{ @@ -8,9 +8,8 @@ use wasmer_types::{ }; use wasmer_vm::{ - FunctionBodyPtr, ImportFunctionEnv, Imports, MemoryStyle, TableStyle, VMFunctionBody, - VMFunctionEnvironment, VMFunctionImport, VMFunctionKind, VMGlobalImport, VMMemoryImport, - VMTableImport, + ContextObjects, FunctionBodyPtr, Imports, MemoryStyle, TableStyle, VMExtern, VMFunctionBody, + VMFunctionImport, VMFunctionKind, VMGlobalImport, VMMemoryImport, VMTableImport, }; /// Get an `ExternType` given a import index. @@ -36,13 +35,13 @@ fn get_extern_from_import(module: &ModuleInfo, import_index: &ImportIndex) -> Ex } /// Get an `ExternType` given an export (and Engine signatures in case is a function). -fn get_extern_from_export(_module: &ModuleInfo, export: &Export) -> ExternType { - match export { - Export::Function(ref f) => ExternType::Function(f.vm_function.signature.clone()), - Export::Table(ref t) => ExternType::Table(*t.ty()), - Export::Memory(ref m) => ExternType::Memory(m.ty()), - Export::Global(ref g) => { - let global = g.from.ty(); +fn get_extern_type(context: &ContextObjects, extern_: &VMExtern) -> ExternType { + match extern_ { + VMExtern::Function(f) => ExternType::Function(f.get(context).signature.clone()), + VMExtern::Table(t) => ExternType::Table(*t.get(context).ty()), + VMExtern::Memory(m) => ExternType::Memory(m.get(context).ty()), + VMExtern::Global(g) => { + let global = g.get(context).ty(); ExternType::Global(*global) } } @@ -54,14 +53,13 @@ fn get_extern_from_export(_module: &ModuleInfo, export: &Export) -> ExternType { /// If all imports are satisfied returns an `Imports` instance required for a module instantiation. pub fn resolve_imports( module: &ModuleInfo, - imports: &[Export], + imports: &[VMExtern], + context: &ContextObjects, finished_dynamic_function_trampolines: &BoxedSlice, memory_styles: &PrimaryMap, _table_styles: &PrimaryMap, ) -> Result { let mut function_imports = PrimaryMap::with_capacity(module.num_imported_functions); - let mut host_function_env_initializers = - PrimaryMap::with_capacity(module.num_imported_functions); let mut table_imports = PrimaryMap::with_capacity(module.num_imported_tables); let mut memory_imports = PrimaryMap::with_capacity(module.num_imported_memories); let mut global_imports = PrimaryMap::with_capacity(module.num_imported_globals); @@ -77,94 +75,60 @@ pub fn resolve_imports( ImportError::UnknownImport(import_extern), )); }; - let export_extern = get_extern_from_export(module, resolved); - if !export_extern.is_compatible_with(&import_extern) { + let extern_type = get_extern_type(context, resolved); + if !extern_type.is_compatible_with(&import_extern) { return Err(LinkError::Import( module_name.to_string(), field.to_string(), - ImportError::IncompatibleType(import_extern, export_extern), + ImportError::IncompatibleType(import_extern, extern_type), )); } - match resolved { - Export::Function(ref f) => { - let address = match f.vm_function.kind { + match *resolved { + VMExtern::Function(handle) => { + let f = handle.get(context); + let address = match f.kind { VMFunctionKind::Dynamic => { // If this is a dynamic imported function, // the address of the function is the address of the // reverse trampoline. let index = FunctionIndex::new(function_imports.len()); finished_dynamic_function_trampolines[index].0 as *mut VMFunctionBody as _ - - // TODO: We should check that the f.vmctx actually matches - // the shape of `VMDynamicFunctionImportContext` - } - VMFunctionKind::Static => f.vm_function.address, - }; - - // Clone the host env for this `Instance`. - let env = if let Some(ExportFunctionMetadata { - host_env_clone_fn: clone, - .. - }) = f.metadata.as_deref() - { - // TODO: maybe start adding asserts in all these - // unsafe blocks to prevent future changes from - // horribly breaking things. - unsafe { - assert!(!f.vm_function.vmctx.host_env.is_null()); - (clone)(f.vm_function.vmctx.host_env) } - } else { - // No `clone` function means we're dealing with some - // other kind of `vmctx`, not a host env of any - // kind. - unsafe { f.vm_function.vmctx.host_env } + VMFunctionKind::Static => unsafe { f.anyfunc.as_ptr().as_ref().func_ptr }, }; function_imports.push(VMFunctionImport { body: address, - environment: VMFunctionEnvironment { host_env: env }, + environment: unsafe { f.anyfunc.as_ptr().as_ref().vmctx }, + handle, }); - - let initializer = f.metadata.as_ref().and_then(|m| m.import_init_function_ptr); - let clone = f.metadata.as_ref().map(|m| m.host_env_clone_fn); - let destructor = f.metadata.as_ref().map(|m| m.host_env_drop_fn); - let import_function_env = - if let (Some(clone), Some(destructor)) = (clone, destructor) { - ImportFunctionEnv::Env { - env, - clone, - initializer, - destructor, + } + VMExtern::Table(handle) => { + let t = handle.get(context); + match import_index { + ImportIndex::Table(index) => { + let import_table_ty = t.ty(); + let expected_table_ty = &module.tables[*index]; + if import_table_ty.ty != expected_table_ty.ty { + return Err(LinkError::Import( + module_name.to_string(), + field.to_string(), + ImportError::IncompatibleType(import_extern, extern_type), + )); } - } else { - ImportFunctionEnv::NoEnv - }; - host_function_env_initializers.push(import_function_env); - } - Export::Table(ref t) => match import_index { - ImportIndex::Table(index) => { - let import_table_ty = t.from.ty(); - let expected_table_ty = &module.tables[*index]; - if import_table_ty.ty != expected_table_ty.ty { - return Err(LinkError::Import( - module_name.to_string(), - field.to_string(), - ImportError::IncompatibleType(import_extern, export_extern), - )); + table_imports.push(VMTableImport { + definition: t.vmtable(), + handle, + }); + } + _ => { + unreachable!("Table resolution did not match"); } - - table_imports.push(VMTableImport { - definition: t.from.vmtable(), - from: t.from.clone(), - }); - } - _ => { - unreachable!("Table resolution did not match"); } - }, - Export::Memory(ref m) => { + } + VMExtern::Memory(handle) => { + let m = handle.get(context); match import_index { ImportIndex::Memory(index) => { // Sanity-check: Ensure that the imported memory has at least @@ -194,15 +158,16 @@ pub fn resolve_imports( } memory_imports.push(VMMemoryImport { - definition: m.from.vmmemory(), - from: m.from.clone(), + definition: m.vmmemory(), + handle, }); } - Export::Global(ref g) => { + VMExtern::Global(handle) => { + let g = handle.get(context); global_imports.push(VMGlobalImport { - definition: g.from.vmglobal(), - from: g.from.clone(), + definition: g.vmglobal(), + handle, }); } } @@ -210,7 +175,6 @@ pub fn resolve_imports( Ok(Imports::new( function_imports, - host_function_env_initializers, table_imports, memory_imports, global_imports, diff --git a/lib/compiler/src/engine/tunables.rs b/lib/compiler/src/engine/tunables.rs index 3fc01cc6292..43d7c1a2d39 100644 --- a/lib/compiler/src/engine/tunables.rs +++ b/lib/compiler/src/engine/tunables.rs @@ -1,14 +1,13 @@ use crate::engine::error::LinkError; use std::ptr::NonNull; -use std::sync::Arc; use wasmer_types::entity::{EntityRef, PrimaryMap}; use wasmer_types::{ GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType, ModuleInfo, TableIndex, TableType, }; -use wasmer_vm::MemoryError; -use wasmer_vm::{Global, Memory, Table}; +use wasmer_vm::{ContextObjects, InternalContextHandle, MemoryError}; use wasmer_vm::{MemoryStyle, TableStyle}; +use wasmer_vm::{VMGlobal, VMMemory, VMTable}; use wasmer_vm::{VMMemoryDefinition, VMTableDefinition}; /// An engine delegates the creation of memories, tables, and globals @@ -25,7 +24,7 @@ pub trait Tunables { &self, ty: &MemoryType, style: &MemoryStyle, - ) -> Result, MemoryError>; + ) -> Result; /// Create a memory owned by the VM given a [`MemoryType`] and a [`MemoryStyle`]. /// @@ -36,14 +35,10 @@ pub trait Tunables { ty: &MemoryType, style: &MemoryStyle, vm_definition_location: NonNull, - ) -> Result, MemoryError>; + ) -> Result; /// Create a table owned by the host given a [`TableType`] and a [`TableStyle`]. - fn create_host_table( - &self, - ty: &TableType, - style: &TableStyle, - ) -> Result, String>; + fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result; /// Create a table owned by the VM given a [`TableType`] and a [`TableStyle`]. /// @@ -54,11 +49,11 @@ pub trait Tunables { ty: &TableType, style: &TableStyle, vm_definition_location: NonNull, - ) -> Result, String>; + ) -> Result; /// Create a global with an unset value. - fn create_global(&self, ty: GlobalType) -> Result, String> { - Ok(Arc::new(Global::new(ty))) + fn create_global(&self, ty: GlobalType) -> Result { + Ok(VMGlobal::new(ty)) } /// Allocate memory for just the memories of the current module. @@ -67,10 +62,11 @@ pub trait Tunables { /// - `memory_definition_locations` must point to a valid locations in VM memory. unsafe fn create_memories( &self, + context: &mut ContextObjects, module: &ModuleInfo, memory_styles: &PrimaryMap, memory_definition_locations: &[NonNull], - ) -> Result>, LinkError> { + ) -> Result>, LinkError> { let num_imports = module.num_imported_memories; let mut memories: PrimaryMap = PrimaryMap::with_capacity(module.memories.len() - num_imports); @@ -83,10 +79,11 @@ pub trait Tunables { let mi = MemoryIndex::new(index); let ty = &module.memories[mi]; let style = &memory_styles[mi]; - memories.push( + memories.push(InternalContextHandle::new( + context, self.create_vm_memory(ty, style, *mdl) .map_err(|e| LinkError::Resource(format!("Failed to create memory: {}", e)))?, - ); + )); } Ok(memories) } @@ -98,10 +95,11 @@ pub trait Tunables { /// To be done unsafe fn create_tables( &self, + context: &mut ContextObjects, module: &ModuleInfo, table_styles: &PrimaryMap, table_definition_locations: &[NonNull], - ) -> Result>, LinkError> { + ) -> Result>, LinkError> { let num_imports = module.num_imported_tables; let mut tables: PrimaryMap = PrimaryMap::with_capacity(module.tables.len() - num_imports); @@ -114,10 +112,11 @@ pub trait Tunables { let ti = TableIndex::new(index); let ty = &module.tables[ti]; let style = &table_styles[ti]; - tables.push( + tables.push(InternalContextHandle::new( + context, self.create_vm_table(ty, style, *tdl) .map_err(LinkError::Resource)?, - ); + )); } Ok(tables) } @@ -126,16 +125,18 @@ pub trait Tunables { /// with initializers applied. fn create_globals( &self, + context: &mut ContextObjects, module: &ModuleInfo, - ) -> Result>, LinkError> { + ) -> Result>, LinkError> { let num_imports = module.num_imported_globals; let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports); for &global_type in module.globals.values().skip(num_imports) { - vmctx_globals.push( + vmctx_globals.push(InternalContextHandle::new( + context, self.create_global(global_type) .map_err(LinkError::Resource)?, - ); + )); } Ok(vmctx_globals) diff --git a/lib/compiler/src/engine/universal/artifact.rs b/lib/compiler/src/engine/universal/artifact.rs index 1ad5f86afc5..abcbb67af16 100644 --- a/lib/compiler/src/engine/universal/artifact.rs +++ b/lib/compiler/src/engine/universal/artifact.rs @@ -18,10 +18,7 @@ use wasmer_types::{ CompileError, DeserializeError, FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo, OwnedDataInitializer, SerializeError, SignatureIndex, TableIndex, }; -use wasmer_vm::{ - FuncDataRegistry, FunctionBodyPtr, MemoryStyle, TableStyle, VMSharedSignatureIndex, - VMTrampoline, -}; +use wasmer_vm::{FunctionBodyPtr, MemoryStyle, TableStyle, VMSharedSignatureIndex, VMTrampoline}; /// A compiled wasm module, ready to be instantiated. pub struct UniversalArtifact { @@ -30,7 +27,6 @@ pub struct UniversalArtifact { finished_function_call_trampolines: BoxedSlice, finished_dynamic_function_trampolines: BoxedSlice, signatures: BoxedSlice, - func_data_registry: Arc, frame_info_registration: Mutex>, finished_function_lengths: BoxedSlice, } @@ -172,7 +168,6 @@ impl UniversalArtifact { let finished_dynamic_function_trampolines = finished_dynamic_function_trampolines.into_boxed_slice(); let signatures = signatures.into_boxed_slice(); - let func_data_registry = engine_inner.func_data().clone(); Ok(Self { artifact, @@ -182,7 +177,6 @@ impl UniversalArtifact { signatures, frame_info_registration: Mutex::new(None), finished_function_lengths, - func_data_registry, }) } /// Get the default extension when serializing this artifact @@ -273,8 +267,4 @@ impl Artifact for UniversalArtifact { fn signatures(&self) -> &BoxedSlice { &self.signatures } - - fn func_data_registry(&self) -> &FuncDataRegistry { - &self.func_data_registry - } } diff --git a/lib/compiler/src/engine/universal/engine.rs b/lib/compiler/src/engine/universal/engine.rs index 28e4281492e..3b292455324 100644 --- a/lib/compiler/src/engine/universal/engine.rs +++ b/lib/compiler/src/engine/universal/engine.rs @@ -15,8 +15,8 @@ use wasmer_types::{ }; use wasmer_types::{CustomSection, CustomSectionProtection, SectionIndex}; use wasmer_vm::{ - FuncDataRegistry, FunctionBodyPtr, SectionBodyPtr, SignatureRegistry, VMCallerCheckedAnyfunc, - VMFuncRef, VMFunctionBody, VMSharedSignatureIndex, VMTrampoline, + FunctionBodyPtr, SectionBodyPtr, SignatureRegistry, VMFunctionBody, VMSharedSignatureIndex, + VMTrampoline, }; /// A WebAssembly `Universal` Engine. @@ -37,7 +37,6 @@ impl UniversalEngine { builder: UniversalEngineBuilder::new(Some(compiler), features), code_memory: vec![], signatures: SignatureRegistry::new(), - func_data: Arc::new(FuncDataRegistry::new()), })), target: Arc::new(target), engine_id: EngineId::default(), @@ -63,7 +62,6 @@ impl UniversalEngine { builder: UniversalEngineBuilder::new(None, Features::default()), code_memory: vec![], signatures: SignatureRegistry::new(), - func_data: Arc::new(FuncDataRegistry::new()), })), target: Arc::new(Target::default()), engine_id: EngineId::default(), @@ -91,11 +89,6 @@ impl Engine for UniversalEngine { compiler.signatures().register(func_type) } - fn register_function_metadata(&self, func_data: VMCallerCheckedAnyfunc) -> VMFuncRef { - let compiler = self.inner(); - compiler.func_data().register(func_data) - } - /// Lookup a signature fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option { let compiler = self.inner(); @@ -154,10 +147,6 @@ pub struct UniversalEngineInner { /// The signature registry is used mainly to operate with trampolines /// performantly. signatures: SignatureRegistry, - /// The backing storage of `VMFuncRef`s. This centralized store ensures that 2 - /// functions with the same `VMCallerCheckedAnyfunc` will have the same `VMFuncRef`. - /// It also guarantees that the `VMFuncRef`s stay valid until the engine is dropped. - func_data: Arc, } impl UniversalEngineInner { @@ -296,9 +285,4 @@ impl UniversalEngineInner { pub fn signatures(&self) -> &SignatureRegistry { &self.signatures } - - /// Shared func metadata registry. - pub(crate) fn func_data(&self) -> &Arc { - &self.func_data - } } diff --git a/lib/derive/src/env/mod.rs b/lib/derive/src/env/mod.rs deleted file mode 100644 index b9558c5dbb7..00000000000 --- a/lib/derive/src/env/mod.rs +++ /dev/null @@ -1,249 +0,0 @@ -use proc_macro2::TokenStream; -use proc_macro_error::{abort, set_dummy}; -use quote::{quote, quote_spanned, ToTokens}; -use syn::{spanned::Spanned, *}; - -mod parse; - -use self::parse::WasmerAttr; - -fn impl_wasmer_env_for_struct( - name: &Ident, - data: &DataStruct, - generics: &Generics, - _attrs: &[Attribute], -) -> TokenStream { - let (trait_methods, helper_methods) = derive_struct_fields(data); - let lifetimes_and_generics = generics.params.clone(); - let where_clause = generics.where_clause.clone(); - quote! { - impl < #lifetimes_and_generics > ::wasmer::WasmerEnv for #name < #lifetimes_and_generics > #where_clause{ - #trait_methods - } - - #[allow(dead_code)] - impl < #lifetimes_and_generics > #name < #lifetimes_and_generics > #where_clause { - #helper_methods - } - } -} - -pub fn impl_wasmer_env(input: &DeriveInput) -> TokenStream { - let struct_name = &input.ident; - - set_dummy(quote! { - impl ::wasmer::WasmerEnv for #struct_name { - fn init_with_instance(&mut self, instance: &::wasmer::Instance) -> ::core::result::Result<(), ::wasmer::HostEnvInitError> { - Ok(()) - } - } - }); - - match &input.data { - Data::Struct(ds) => { - impl_wasmer_env_for_struct(struct_name, ds, &input.generics, &input.attrs) - } - _ => todo!(), - } - /*match input.data { - Struct(ds /*DataStruct { - fields: syn::Fields::Named(ref fields), - .. - }*/) => , - Enum(ref e) => impl_wasmer_env_for_enum(struct_name, &e.variants, &input.attrs), - _ => abort_call_site!("Clap only supports non-tuple structs and enums"), - }*/ -} - -fn derive_struct_fields(data: &DataStruct) -> (TokenStream, TokenStream) { - let mut finish = vec![]; - let mut helpers = vec![]; - //let mut assign_tokens = vec![]; - let mut touched_fields = vec![]; - let fields: Vec = match &data.fields { - Fields::Named(ref fields) => fields.named.iter().cloned().collect(), - Fields::Unit => vec![], - Fields::Unnamed(fields) => fields.unnamed.iter().cloned().collect(), - }; - for (field_num, f) in fields.into_iter().enumerate() { - let field_idx = syn::Index::from(field_num); - let name = f.ident.clone(); - let top_level_ty: &Type = &f.ty; - touched_fields.push(name.clone()); - let mut wasmer_attr = None; - for attr in &f.attrs { - // if / filter - if attr.path.is_ident(&Ident::new("wasmer", attr.span())) { - let tokens = attr.tokens.clone(); - match syn::parse2(tokens) { - Ok(attr) => { - wasmer_attr = Some(attr); - break; - } - Err(e) => { - abort!(attr, "Failed to parse `wasmer` attribute: {}", e); - } - } - } - } - - if let Some(wasmer_attr) = wasmer_attr { - let inner_type = get_identifier(top_level_ty); - if let Some(name) = &name { - let name_ref_str = format!("{}_ref", name); - let name_ref = syn::Ident::new(&name_ref_str, name.span()); - let name_ref_unchecked_str = format!("{}_ref_unchecked", name); - let name_ref_unchecked = syn::Ident::new(&name_ref_unchecked_str, name.span()); - let helper_tokens = quote_spanned! {f.span()=> - /// Get access to the underlying data. - /// - /// If `WasmerEnv::finish` has been called, this function will never - /// return `None` unless the underlying data has been mutated manually. - pub fn #name_ref(&self) -> Option<&#inner_type> { - self.#name.get_ref() - } - /// Gets the item without checking if it's been initialized. - /// - /// # Safety - /// `WasmerEnv::finish` must have been called on this function or - /// this type manually initialized. - pub unsafe fn #name_ref_unchecked(&self) -> &#inner_type { - self.#name.get_unchecked() - } - }; - helpers.push(helper_tokens); - } - match wasmer_attr { - WasmerAttr::Export { - identifier, - optional, - aliases, - span, - } => { - let finish_tokens = if let Some(name) = name { - let name_str = name.to_string(); - let item_name = - identifier.unwrap_or_else(|| LitStr::new(&name_str, name.span())); - let mut access_expr = quote_spanned! { - f.span() => - instance.exports.get_with_generics_weak::<#inner_type, _, _>(#item_name) - }; - for alias in aliases { - access_expr = quote_spanned! { - f.span()=> - #access_expr .or_else(|_| instance.exports.get_with_generics_weak::<#inner_type, _, _>(#alias)) - }; - } - if optional { - quote_spanned! { - f.span()=> - if let Ok(#name) = #access_expr { - self.#name.initialize(#name); - }; - } - } else { - quote_spanned! { - f.span()=> - let #name: #inner_type = #access_expr?; - self.#name.initialize(#name); - } - } - } else if let Some(identifier) = identifier { - let mut access_expr = quote_spanned! { - f.span() => - instance.exports.get_with_generics_weak::<#inner_type, _, _>(#identifier) - }; - for alias in aliases { - access_expr = quote_spanned! { - f.span()=> - #access_expr .or_else(|_| instance.exports.get_with_generics_weak::<#inner_type, _, _>(#alias)) - }; - } - let local_var = - Ident::new(&format!("field_{}", field_num), identifier.span()); - if optional { - quote_spanned! { - f.span()=> - if let Ok(#local_var) = #access_expr { - self.#field_idx.initialize(#local_var); - } - } - } else { - quote_spanned! { - f.span()=> - let #local_var: #inner_type = #access_expr?; - self.#field_idx.initialize(#local_var); - } - } - } else { - abort!( - span, - "Expected `name` field on export attribute because field does not have a name. For example: `#[wasmer(export(name = \"wasm_ident\"))]`.", - ); - }; - - finish.push(finish_tokens); - } - } - } - } - - let trait_methods = quote! { - fn init_with_instance(&mut self, instance: &::wasmer::Instance) -> ::core::result::Result<(), ::wasmer::HostEnvInitError> { - #(#finish)* - Ok(()) - } - }; - - let helper_methods = quote! { - #(#helpers)* - }; - - (trait_methods, helper_methods) -} - -// TODO: name this something that makes sense -fn get_identifier(ty: &Type) -> TokenStream { - match ty { - Type::Path(TypePath { - path: Path { segments, .. }, - .. - }) => { - if let Some(PathSegment { ident, arguments }) = segments.last() { - if ident != "LazyInit" { - abort!( - ident, - "WasmerEnv derive expects all `export`s to be wrapped in `LazyInit`" - ); - } - if let PathArguments::AngleBracketed(AngleBracketedGenericArguments { - args, .. - }) = arguments - { - // TODO: proper error handling - assert_eq!(args.len(), 1); - if let GenericArgument::Type(Type::Path(TypePath { - path: Path { segments, .. }, - .. - })) = &args[0] - { - segments - .last() - .expect("there must be at least one segment; TODO: error handling") - .to_token_stream() - } else { - abort!( - &args[0], - "unrecognized type in first generic position on `LazyInit`" - ); - } - } else { - abort!(arguments, "Expected a generic parameter on `LazyInit`"); - } - } else { - abort!(segments, "Unknown type found"); - } - } - _ => abort!(ty, "Unrecognized/unsupported type"), - } -} diff --git a/lib/derive/src/env/parse.rs b/lib/derive/src/env/parse.rs deleted file mode 100644 index a8feb9e9488..00000000000 --- a/lib/derive/src/env/parse.rs +++ /dev/null @@ -1,143 +0,0 @@ -use proc_macro2::Span; -use proc_macro_error::abort; -use syn::{ - parenthesized, - parse::{Parse, ParseStream}, - token, Ident, LitBool, LitStr, Token, -}; - -pub enum WasmerAttr { - Export { - /// The identifier is an override, otherwise we use the field name as the name - /// to lookup in `instance.exports`. - identifier: Option, - optional: bool, - aliases: Vec, - span: Span, - }, -} - -#[derive(Debug)] -struct ExportExpr { - name: Option, - optional: bool, - aliases: Vec, -} - -#[derive(Debug)] -struct ExportOptions { - name: Option, - optional: bool, - aliases: Vec, -} -impl Parse for ExportOptions { - fn parse(input: ParseStream<'_>) -> syn::Result { - let mut name = None; - let mut optional: bool = false; - let mut aliases: Vec = vec![]; - loop { - let ident = input.parse::()?; - let _ = input.parse::()?; - let ident_str = ident.to_string(); - - match ident_str.as_str() { - "name" => { - name = Some(input.parse::()?); - } - "optional" => { - optional = input.parse::()?.value; - } - "alias" => { - let alias = input.parse::()?; - aliases.push(alias); - } - otherwise => { - abort!( - ident, - "Unrecognized argument in export options: expected `name = \"string\"`, `optional = bool`, or `alias = \"string\"` found `{}`", - otherwise - ); - } - } - - match input.parse::() { - Ok(_) => continue, - Err(_) => break, - } - } - - Ok(ExportOptions { - name, - optional, - aliases, - }) - } -} - -impl Parse for ExportExpr { - fn parse(input: ParseStream<'_>) -> syn::Result { - let name; - let optional; - let aliases; - if input.peek(Ident) { - let options = input.parse::()?; - name = options.name; - optional = options.optional; - aliases = options.aliases; - } else { - name = None; - optional = false; - aliases = vec![]; - } - Ok(Self { - name, - optional, - aliases, - }) - } -} - -// allows us to handle parens more cleanly -struct WasmerAttrInner(WasmerAttr); - -impl Parse for WasmerAttrInner { - fn parse(input: ParseStream<'_>) -> syn::Result { - let ident: Ident = input.parse()?; - let ident_str = ident.to_string(); - let span = ident.span(); - let out = match ident_str.as_str() { - "export" => { - let export_expr; - let (name, optional, aliases) = if input.peek(token::Paren) { - let _: token::Paren = parenthesized!(export_expr in input); - - let expr = export_expr.parse::()?; - (expr.name, expr.optional, expr.aliases) - } else { - (None, false, vec![]) - }; - - WasmerAttr::Export { - identifier: name, - optional, - aliases, - span, - } - } - otherwise => abort!( - ident, - "Unexpected identifier `{}`. Expected `export`.", - otherwise - ), - }; - Ok(WasmerAttrInner(out)) - } -} - -impl Parse for WasmerAttr { - fn parse(input: ParseStream<'_>) -> syn::Result { - let attr_inner; - parenthesized!(attr_inner in input); - Ok(attr_inner.parse::()?.0) - } -} diff --git a/lib/derive/src/lib.rs b/lib/derive/src/lib.rs index 8a37a88e184..fe781efff80 100644 --- a/lib/derive/src/lib.rs +++ b/lib/derive/src/lib.rs @@ -3,17 +3,8 @@ extern crate proc_macro; use proc_macro_error::proc_macro_error; use syn::{parse_macro_input, DeriveInput}; -mod env; mod value_type; -#[proc_macro_error] -#[proc_macro_derive(WasmerEnv, attributes(wasmer))] -pub fn derive_wasmer_env(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - let gen = env::impl_wasmer_env(&input); - gen.into() -} - #[proc_macro_error] #[proc_macro_derive(ValueType)] pub fn derive_value_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream { diff --git a/lib/types/Cargo.toml b/lib/types/Cargo.toml index 3c8fda7de0d..f91e02b5d90 100644 --- a/lib/types/Cargo.toml +++ b/lib/types/Cargo.toml @@ -24,6 +24,3 @@ default = ["std", "enable-serde"] std = [] core = [] enable-serde = ["serde", "serde/std", "serde_bytes"] - -# experimental / in-development features -experimental-reference-types-extern-ref = [] diff --git a/lib/types/src/extern_ref.rs b/lib/types/src/extern_ref.rs deleted file mode 100644 index d477c17b930..00000000000 --- a/lib/types/src/extern_ref.rs +++ /dev/null @@ -1,294 +0,0 @@ -use std::any::Any; -use std::ptr; -use std::sync::atomic; - -/// This type does not do reference counting automatically, reference counting can be done with -/// [`Self::ref_clone`] and [`Self::ref_drop`]. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(transparent)] -pub struct VMExternRef(*const VMExternRefInner); - -impl VMExternRef { - /// The maximum number of references allowed to this data. - const MAX_REFCOUNT: usize = std::usize::MAX - 1; - - /// Checks if the given ExternRef is null. - pub fn is_null(&self) -> bool { - self.0.is_null() - } - - /// New null extern ref - pub const fn null() -> Self { - Self(ptr::null()) - } - - /// Get a bit-level representation of an externref. - /// For internal use for packing / unpacking it for calling functions. - pub(crate) fn to_binary(self) -> i128 { - self.0 as i128 - } - - /// Create an externref from bit-level representation. - /// For internal use for packing / unpacking it for calling functions. - /// - /// # Safety - /// The pointer is assumed valid or null. Passing arbitrary data to this function will - /// result in undefined behavior. It is the caller's responsibility to verify that only - /// valid externref bit patterns are passed to this function. - pub(crate) unsafe fn from_binary(bits: i128) -> Self { - Self(bits as usize as *const _) - } - - /// Make a new extern reference - pub fn new(value: T) -> Self - where - T: Any + Send + Sync + 'static + Sized, - { - Self(Box::into_raw(Box::new(VMExternRefInner::new::(value)))) - } - - /// Try to downcast to the given value - pub fn downcast(&self) -> Option<&T> - where - T: Any + Send + Sync + 'static + Sized, - { - if self.is_null() { - return None; - } - unsafe { - let inner = &*self.0; - - inner.data.downcast_ref::() - } - } - - /// Panic if the ref count gets too high. - #[track_caller] - fn sanity_check_ref_count(old_size: usize, growth_amount: usize) { - // If we exceed 18_446_744_073_709_551_614 references on a 64bit system (or - // 2_147_483_646 references on a 32bit system) then we either live in a future with - // magic technology or we have a bug in our ref counting logic (i.e. a leak). - // Either way, the best course of action is to terminate the program and update - // some code on our side. - // - // Note to future readers: exceeding `usize` ref count is trivially provable as a - // bug on systems that can address `usize` sized memory blocks or smaller because - // the reference itself is at least `usize` in size and all virtual memory would be - // taken by references to the data leaving no room for the data itself. - if old_size - .checked_add(growth_amount) - .map_or(true, |v| v > Self::MAX_REFCOUNT) - { - panic!("Too many references to `ExternRef`"); - } - } - - /// A low-level function to increment the strong-count a given number of times. - /// - /// This is used as an optimization when implementing some low-level VM primitives. - /// If you're using this type directly for whatever reason, you probably want - /// [`Self::ref_clone`] instead. - pub fn ref_inc_by(&self, val: usize) { - if self.0.is_null() { - return; - } - - let old_size = unsafe { - let ref_inner = &*self.0; - ref_inner.increment_ref_count(val) - }; - - Self::sanity_check_ref_count(old_size, val); - } - - /// A deep copy of the reference, increments the strong count. - pub fn ref_clone(&self) -> Self { - if self.0.is_null() { - return Self(self.0); - } - - let old_size = unsafe { - let ref_inner = &*self.0; - ref_inner.increment_ref_count(1) - }; - - // See comments in [`Self::sanity_check_ref_count`] for more information. - if old_size > Self::MAX_REFCOUNT { - panic!("Too many references to `ExternRef`"); - } - - Self(self.0) - } - - /// Does an inner drop, decrementing the strong count - pub fn ref_drop(&mut self) { - if !self.0.is_null() { - unsafe { - let should_drop = { - let ref_inner: &VMExternRefInner = &*self.0; - ref_inner.decrement_and_drop() - }; - if should_drop { - let _ = Box::from_raw(self.0 as *mut VMExternRefInner); - } - } - } - } - - #[allow(dead_code)] - /// Get the number of strong references to this data. - fn strong_count(&self) -> usize { - if self.0.is_null() { - 0 - } else { - unsafe { (*self.0).strong.load(atomic::Ordering::SeqCst) } - } - } -} - -#[derive(Debug)] -#[repr(C)] -pub(crate) struct VMExternRefInner { - strong: atomic::AtomicUsize, - /// Do something obviously correct to get started. This can "easily" be improved - /// to be an inline allocation later as the logic is fully encapsulated. - data: Box, -} - -impl VMExternRefInner { - fn new(value: T) -> Self - where - T: Any + Send + Sync + Sized + 'static, - { - Self { - strong: atomic::AtomicUsize::new(1), - data: Box::new(value), - } - } - - /// Increments the reference count. - /// Returns the old value. - fn increment_ref_count(&self, val: usize) -> usize { - // Using a relaxed ordering is alright here, as knowledge of - // the original reference prevents other threads from - // erroneously deleting the object. - // - // As explained in the [Boost documentation][1]: - // - // > Increasing the reference counter can always be done with - // > `memory_order_relaxed`: New references to an object can - // > only be formed from an existing reference, and passing an - // > existing reference from one thread to another must already - // > provide any required synchronization. - // - // [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html - self.strong.fetch_add(val, atomic::Ordering::Relaxed) - } - - /// Decrement the count and drop the data if the count hits 0 - /// returns `true` if the containing allocation should be dropped - fn decrement_and_drop(&self) -> bool { - // Because `fetch_sub` is already atomic, we do not need to - // synchronize with other thread. - if self.strong.fetch_sub(1, atomic::Ordering::Release) != 1 { - return false; - } - - // This fence is needed to prevent reordering of use of the data and - // deletion of the data. Because it is marked `Release`, the decreasing - // of the reference count synchronizes with this `Acquire` fence. This - // means that use of the data happens before decreasing the reference - // count, which happens before this fence, which happens before the - // deletion of the data. - // - // As explained in the [Boost documentation][1]: - // - // > It is important to enforce any possible access to the object in one - // > thread (through an existing reference) to *happen before* deleting - // > the object in a different thread. This is achieved by a "release" - // > operation after dropping a reference (any access to the object - // > through this reference must obviously happened before), and an - // > "acquire" operation before deleting the object. - // - // [1]: https://www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html - atomic::fence(atomic::Ordering::Acquire); - - true - } -} - -#[derive(Debug, PartialEq, Eq)] -#[repr(transparent)] -/// An opaque reference to some data. This reference can be passed through Wasm. -pub struct ExternRef { - inner: VMExternRef, -} - -impl Clone for ExternRef { - fn clone(&self) -> Self { - Self { - inner: self.inner.ref_clone(), - } - } -} - -impl Drop for ExternRef { - fn drop(&mut self) { - self.inner.ref_drop() - } -} - -impl ExternRef { - /// Checks if the given ExternRef is null. - pub fn is_null(&self) -> bool { - self.inner.is_null() - } - - /// New null extern ref - pub fn null() -> Self { - Self { - inner: VMExternRef::null(), - } - } - - #[cfg(feature = "experimental-reference-types-extern-ref")] - /// Make a new extern reference - pub fn new(value: T) -> Self - where - T: Any + Send + Sync + 'static + Sized, - { - Self { - inner: VMExternRef::new(value), - } - } - - #[cfg(feature = "experimental-reference-types-extern-ref")] - /// Try to downcast to the given value - pub fn downcast(&self) -> Option<&T> - where - T: Any + Send + Sync + 'static + Sized, - { - self.inner.downcast::() - } - - #[cfg(feature = "experimental-reference-types-extern-ref")] - /// Get the number of strong references to this data. - pub fn strong_count(&self) -> usize { - self.inner.strong_count() - } -} - -impl From for ExternRef { - fn from(other: VMExternRef) -> Self { - Self { inner: other } - } -} - -impl From for VMExternRef { - fn from(other: ExternRef) -> Self { - let out = other.inner; - // We want to make this transformation without decrementing the count. - std::mem::forget(other); - out - } -} diff --git a/lib/types/src/indexes.rs b/lib/types/src/indexes.rs index ac2a2bc6b40..148f4fe3af9 100644 --- a/lib/types/src/indexes.rs +++ b/lib/types/src/indexes.rs @@ -219,7 +219,17 @@ entity_impl!(ArchivedCustomSectionIndex); /// An entity to export. #[derive( - Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, RkyvSerialize, RkyvDeserialize, Archive, + Copy, + Clone, + Debug, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + RkyvSerialize, + RkyvDeserialize, + Archive, )] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[archive_attr(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug))] diff --git a/lib/types/src/lib.rs b/lib/types/src/lib.rs index 51cf8193e94..da185329db3 100644 --- a/lib/types/src/lib.rs +++ b/lib/types/src/lib.rs @@ -55,20 +55,18 @@ pub mod lib { pub mod compilation; pub mod error; -mod extern_ref; mod features; mod indexes; mod initializers; mod libcalls; mod memory; mod module; -mod native; mod table; mod trapcode; mod types; mod units; mod utils; -mod values; +mod value; mod vmoffsets; pub use error::{ @@ -78,7 +76,6 @@ pub use error::{ /// The entity module, with common helpers for Rust structures pub mod entity; -pub use crate::extern_ref::{ExternRef, VMExternRef}; pub use crate::features::Features; pub use crate::indexes::{ CustomSectionIndex, DataIndex, ElemIndex, ExportIndex, FunctionIndex, GlobalIndex, ImportIndex, @@ -90,15 +87,14 @@ pub use crate::initializers::{ }; pub use crate::memory::{Memory32, Memory64, MemorySize}; pub use crate::module::{ExportsIterator, ImportsIterator, ModuleInfo}; -pub use crate::native::{NativeWasmType, ValueType}; pub use crate::units::{ Bytes, PageCountOutOfRange, Pages, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE, }; -pub use crate::values::{Value, WasmValueType}; pub use types::{ ExportType, ExternType, FunctionType, GlobalInit, GlobalType, ImportType, MemoryType, Mutability, TableType, Type, V128, }; +pub use value::{RawValue, ValueType}; pub use crate::libcalls::LibCall; pub use crate::memory::MemoryStyle; @@ -133,3 +129,64 @@ pub type Addend = i64; /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + +mod native { + use super::Type; + use std::fmt; + + /// `NativeWasmType` represents a Wasm type that has a direct + /// representation on the host (hence the “native” term). + /// + /// It uses the Rust Type system to automatically detect the + /// Wasm type associated with a native Rust type. + /// + /// ``` + /// use wasmer_types::{NativeWasmType, Type}; + /// use wasmer_types::{NativeWasmType, Type}; + /// + /// let wasm_type = i32::WASM_TYPE; + /// assert_eq!(wasm_type, Type::I32); + /// ``` + /// + /// > Note: This strategy will be needed later to + /// > automatically detect the signature of a Rust function. + pub trait NativeWasmType: Sized { + /// The ABI for this type (i32, i64, f32, f64) + type Abi: Copy + fmt::Debug; + + /// Type for this `NativeWasmType`. + const WASM_TYPE: Type; + } + + impl NativeWasmType for i32 { + const WASM_TYPE: Type = Type::I32; + type Abi = Self; + } + + impl NativeWasmType for i64 { + const WASM_TYPE: Type = Type::I64; + type Abi = Self; + } + + impl NativeWasmType for f32 { + const WASM_TYPE: Type = Type::F32; + type Abi = Self; + } + + impl NativeWasmType for f64 { + const WASM_TYPE: Type = Type::F64; + type Abi = Self; + } + + impl NativeWasmType for u128 { + const WASM_TYPE: Type = Type::V128; + type Abi = Self; + } + + impl NativeWasmType for Option { + const WASM_TYPE: Type = T::WASM_TYPE; + type Abi = T::Abi; + } +} + +pub use crate::native::*; diff --git a/lib/types/src/native.rs b/lib/types/src/native.rs deleted file mode 100644 index 45d7c8c3c6a..00000000000 --- a/lib/types/src/native.rs +++ /dev/null @@ -1,300 +0,0 @@ -//! This module permits to create native functions -//! easily in Rust, thanks to its advanced typing system. - -use crate::extern_ref::VMExternRef; -use crate::lib::std::fmt; -use crate::types::Type; -use crate::values::{Value, WasmValueType}; -use std::marker::PhantomData; -use std::mem::MaybeUninit; - -/// `NativeWasmType` represents a Wasm type that has a direct -/// representation on the host (hence the “native” term). -/// -/// It uses the Rust Type system to automatically detect the -/// Wasm type associated with a native Rust type. -/// -/// ``` -/// use wasmer_types::{NativeWasmType, Type}; -/// -/// let wasm_type = i32::WASM_TYPE; -/// assert_eq!(wasm_type, Type::I32); -/// ``` -/// -/// > Note: This strategy will be needed later to -/// > automatically detect the signature of a Rust function. -pub trait NativeWasmType: Sized { - /// The ABI for this type (i32, i64, f32, f64) - type Abi: Copy + fmt::Debug; - - /// Type for this `NativeWasmType`. - const WASM_TYPE: Type; - - #[doc(hidden)] - fn from_abi(abi: Self::Abi) -> Self; - - #[doc(hidden)] - fn into_abi(self) -> Self::Abi; - - /// Convert self to i128 binary representation. - fn to_binary(self) -> i128; - - /// Convert self to a `Value`. - fn to_value(self) -> Value { - let binary = self.to_binary(); - // we need a store, we're just hoping we don't actually use it via funcref - // TODO(reftypes): we need an actual solution here - let hack = 3; - - unsafe { Value::read_value_from(&hack, &binary, Self::WASM_TYPE) } - } - - /// Convert to self from i128 binary representation. - fn from_binary(binary: i128) -> Self; -} - -impl NativeWasmType for i32 { - const WASM_TYPE: Type = Type::I32; - type Abi = Self; - - #[inline] - fn from_abi(abi: Self::Abi) -> Self { - abi - } - - #[inline] - fn into_abi(self) -> Self::Abi { - self - } - - #[inline] - fn to_binary(self) -> i128 { - self as _ - } - - #[inline] - fn from_binary(bits: i128) -> Self { - bits as _ - } -} - -impl NativeWasmType for i64 { - const WASM_TYPE: Type = Type::I64; - type Abi = Self; - - #[inline] - fn from_abi(abi: Self::Abi) -> Self { - abi - } - - #[inline] - fn into_abi(self) -> Self::Abi { - self - } - - #[inline] - fn to_binary(self) -> i128 { - self as _ - } - - #[inline] - fn from_binary(bits: i128) -> Self { - bits as _ - } -} - -impl NativeWasmType for f32 { - const WASM_TYPE: Type = Type::F32; - type Abi = Self; - - #[inline] - fn from_abi(abi: Self::Abi) -> Self { - abi - } - - #[inline] - fn into_abi(self) -> Self::Abi { - self - } - - #[inline] - fn to_binary(self) -> i128 { - self.to_bits() as _ - } - - #[inline] - fn from_binary(bits: i128) -> Self { - Self::from_bits(bits as _) - } -} - -impl NativeWasmType for f64 { - const WASM_TYPE: Type = Type::F64; - type Abi = Self; - - #[inline] - fn from_abi(abi: Self::Abi) -> Self { - abi - } - - #[inline] - fn into_abi(self) -> Self::Abi { - self - } - - #[inline] - fn to_binary(self) -> i128 { - self.to_bits() as _ - } - - #[inline] - fn from_binary(bits: i128) -> Self { - Self::from_bits(bits as _) - } -} - -impl NativeWasmType for u128 { - const WASM_TYPE: Type = Type::V128; - type Abi = Self; - - #[inline] - fn from_abi(abi: Self::Abi) -> Self { - abi - } - - #[inline] - fn into_abi(self) -> Self::Abi { - self - } - - #[inline] - fn to_binary(self) -> i128 { - self as _ - } - - #[inline] - fn from_binary(bits: i128) -> Self { - bits as _ - } -} - -impl NativeWasmType for VMExternRef { - const WASM_TYPE: Type = Type::ExternRef; - type Abi = Self; - - #[inline] - fn from_abi(abi: Self::Abi) -> Self { - abi - } - - #[inline] - fn into_abi(self) -> Self::Abi { - self - } - - #[inline] - fn to_binary(self) -> i128 { - self.to_binary() - } - - #[inline] - fn from_binary(bits: i128) -> Self { - // TODO(reftypes): ensure that the safety invariants are actually upheld here - unsafe { Self::from_binary(bits) } - } -} - -#[cfg(test)] -mod test_native_type { - use super::*; - use crate::types::Type; - - #[test] - fn test_wasm_types() { - assert_eq!(i32::WASM_TYPE, Type::I32); - assert_eq!(i64::WASM_TYPE, Type::I64); - assert_eq!(f32::WASM_TYPE, Type::F32); - assert_eq!(f64::WASM_TYPE, Type::F64); - assert_eq!(u128::WASM_TYPE, Type::V128); - } - - #[test] - fn test_roundtrip() { - assert_eq!(i32::from_binary(42i32.to_binary()), 42i32); - assert_eq!(i64::from_binary(42i64.to_binary()), 42i64); - assert_eq!(f32::from_binary(42f32.to_binary()), 42f32); - assert_eq!(f64::from_binary(42f64.to_binary()), 42f64); - assert_eq!(u128::from_binary(42u128.to_binary()), 42u128); - } -} - -// pub trait IntegerAtomic -// where -// Self: Sized -// { -// type Primitive; - -// fn add(&self, other: Self::Primitive) -> Self::Primitive; -// fn sub(&self, other: Self::Primitive) -> Self::Primitive; -// fn and(&self, other: Self::Primitive) -> Self::Primitive; -// fn or(&self, other: Self::Primitive) -> Self::Primitive; -// fn xor(&self, other: Self::Primitive) -> Self::Primitive; -// fn load(&self) -> Self::Primitive; -// fn store(&self, other: Self::Primitive) -> Self::Primitive; -// fn compare_exchange(&self, expected: Self::Primitive, new: Self::Primitive) -> Self::Primitive; -// fn swap(&self, other: Self::Primitive) -> Self::Primitive; -// } - -/// Trait for a Value type. A Value type is a type that is always valid and may -/// be safely copied. -/// -/// # Safety -/// -/// To maintain safety, types which implement this trait must be valid for all -/// bit patterns. This means that it cannot contain enums, `bool`, references, -/// etc. -/// -/// Concretely a `u32` is a Value type because every combination of 32 bits is -/// a valid `u32`. However a `bool` is _not_ a Value type because any bit patterns -/// other than `0` and `1` are invalid in Rust and may cause undefined behavior if -/// a `bool` is constructed from those bytes. -/// -/// Additionally this trait has a method which zeros out any uninitializes bytes -/// prior to writing them to Wasm memory, which prevents information leaks into -/// the sandbox. -pub unsafe trait ValueType: Copy { - /// This method is passed a byte slice which contains the byte - /// representation of `self`. It must zero out any bytes which are - /// uninitialized (e.g. padding bytes). - fn zero_padding_bytes(&self, bytes: &mut [MaybeUninit]); -} - -// Trivial implementations for primitive types and arrays of them. -macro_rules! primitives { - ($($t:ident)*) => ($( - unsafe impl ValueType for $t { - #[inline] - fn zero_padding_bytes(&self, _bytes: &mut [MaybeUninit]) {} - } - unsafe impl ValueType for [$t; N] { - #[inline] - fn zero_padding_bytes(&self, _bytes: &mut [MaybeUninit]) {} - } - )*) -} -primitives! { - i8 u8 - i16 u16 - i32 u32 - i64 u64 - i128 u128 - isize usize - f32 f64 -} - -// This impl for PhantomData allows #[derive(ValueType)] to work with types -// that contain a PhantomData. -unsafe impl ValueType for PhantomData { - #[inline] - fn zero_padding_bytes(&self, _bytes: &mut [MaybeUninit]) {} -} diff --git a/lib/types/src/types.rs b/lib/types/src/types.rs index 352e84117f5..bb27cbdb9df 100644 --- a/lib/types/src/types.rs +++ b/lib/types/src/types.rs @@ -5,7 +5,6 @@ use crate::lib::std::format; use crate::lib::std::string::{String, ToString}; use crate::lib::std::vec::Vec; use crate::units::Pages; -use crate::values::{Value, WasmValueType}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] @@ -420,31 +419,6 @@ pub enum GlobalInit { RefFunc(FunctionIndex), } -impl Eq for GlobalInit {} - -impl GlobalInit { - /// Get the `GlobalInit` from a given `Value` - pub fn from_value(value: Value) -> Self { - match value { - Value::I32(i) => Self::I32Const(i), - Value::I64(i) => Self::I64Const(i), - Value::F32(f) => Self::F32Const(f), - Value::F64(f) => Self::F64Const(f), - _ => unimplemented!("GlobalInit from_value for {:?}", value), - } - } - /// Get the `Value` from the Global init value - pub fn to_value(&self) -> Value { - match self { - Self::I32Const(i) => Value::I32(*i), - Self::I64Const(i) => Value::I64(*i), - Self::F32Const(f) => Value::F32(*f), - Self::F64Const(f) => Value::F64(*f), - _ => unimplemented!("GlobalInit to_value for {:?}", self), - } - } -} - // Table Types /// A descriptor for a table in a WebAssembly module. diff --git a/lib/types/src/value.rs b/lib/types/src/value.rs new file mode 100644 index 00000000000..8e822d79146 --- /dev/null +++ b/lib/types/src/value.rs @@ -0,0 +1,88 @@ +use core::{fmt, marker::PhantomData, mem::MaybeUninit}; + +/// Raw representation of a WebAssembly value. +/// +/// In most cases you will want to use the type-safe `Value` wrapper instead. +#[allow(missing_docs)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union RawValue { + pub i32: i32, + pub i64: i64, + pub u32: u32, + pub u64: u64, + pub f32: f32, + pub f64: f64, + pub u128: u128, + pub funcref: usize, + pub externref: usize, + pub bytes: [u8; 16], +} + +impl Default for RawValue { + fn default() -> Self { + Self { bytes: [0; 16] } + } +} + +impl fmt::Debug for RawValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RawValue") + .field("bytes", unsafe { &self.bytes }) + .finish() + } +} + +/// Trait for a Value type. A Value type is a type that is always valid and may +/// be safely copied. +/// +/// # Safety +/// +/// To maintain safety, types which implement this trait must be valid for all +/// bit patterns. This means that it cannot contain enums, `bool`, references, +/// etc. +/// +/// Concretely a `u32` is a Value type because every combination of 32 bits is +/// a valid `u32`. However a `bool` is _not_ a Value type because any bit patterns +/// other than `0` and `1` are invalid in Rust and may cause undefined behavior if +/// a `bool` is constructed from those bytes. +/// +/// Additionally this trait has a method which zeros out any uninitializes bytes +/// prior to writing them to Wasm memory, which prevents information leaks into +/// the sandbox. +pub unsafe trait ValueType: Copy { + /// This method is passed a byte slice which contains the byte + /// representation of `self`. It must zero out any bytes which are + /// uninitialized (e.g. padding bytes). + fn zero_padding_bytes(&self, bytes: &mut [MaybeUninit]); +} + +// Trivial implementations for primitive types and arrays of them. +macro_rules! primitives { + ($($t:ident)*) => ($( + unsafe impl ValueType for $t { + #[inline] + fn zero_padding_bytes(&self, _bytes: &mut [MaybeUninit]) {} + } + unsafe impl ValueType for [$t; N] { + #[inline] + fn zero_padding_bytes(&self, _bytes: &mut [MaybeUninit]) {} + } + )*) +} +primitives! { + i8 u8 + i16 u16 + i32 u32 + i64 u64 + i128 u128 + isize usize + f32 f64 +} + +// This impl for PhantomData allows #[derive(ValueType)] to work with types +// that contain a PhantomData. +unsafe impl ValueType for PhantomData { + #[inline] + fn zero_padding_bytes(&self, _bytes: &mut [MaybeUninit]) {} +} diff --git a/lib/types/src/vmoffsets.rs b/lib/types/src/vmoffsets.rs index 06fd6f2d25d..8c3f43c2ae5 100644 --- a/lib/types/src/vmoffsets.rs +++ b/lib/types/src/vmoffsets.rs @@ -256,9 +256,9 @@ impl VMOffsets { 0 * self.pointer_size } - /// The offset of the `from` field. + /// The offset of the `handle` field. #[allow(clippy::identity_op)] - pub const fn vmtable_import_from(&self) -> u8 { + pub const fn vmtable_import_handle(&self) -> u8 { 1 * self.pointer_size } @@ -301,9 +301,9 @@ impl VMOffsets { 0 * self.pointer_size } - /// The offset of the `from` field. + /// The offset of the `handle` field. #[allow(clippy::identity_op)] - pub const fn vmmemory_import_from(&self) -> u8 { + pub const fn vmmemory_import_handle(&self) -> u8 { 1 * self.pointer_size } @@ -346,9 +346,9 @@ impl VMOffsets { 0 * self.pointer_size } - /// The offset of the `from` field. + /// The offset of the `handle` field. #[allow(clippy::identity_op)] - pub const fn vmglobal_import_from(&self) -> u8 { + pub const fn vmglobal_import_handle(&self) -> u8 { 1 * self.pointer_size } @@ -675,9 +675,9 @@ impl VMOffsets { } /// Return the offset to the `vmctx` field in `VMMemoryImport` index `index`. - pub fn vmctx_vmmemory_import_from(&self, index: MemoryIndex) -> u32 { + pub fn vmctx_vmmemory_import_handle(&self, index: MemoryIndex) -> u32 { self.vmctx_vmmemory_import(index) - .checked_add(u32::from(self.vmmemory_import_from())) + .checked_add(u32::from(self.vmmemory_import_handle())) .unwrap() } diff --git a/lib/vm/src/context.rs b/lib/vm/src/context.rs new file mode 100644 index 00000000000..2093418af6c --- /dev/null +++ b/lib/vm/src/context.rs @@ -0,0 +1,251 @@ +use std::{ + cell::UnsafeCell, + fmt, + marker::PhantomData, + num::{NonZeroU64, NonZeroUsize}, + ptr::NonNull, + sync::atomic::{AtomicU64, Ordering}, +}; + +use crate::VMExternObj; + +use crate::{InstanceHandle, VMFunction, VMGlobal, VMMemory, VMTable}; + +/// Unique ID to identify a context. +/// +/// Every handle to an object managed by a context also contains the ID of the +/// context. This is used to check that a handle is always used with the +/// correct context. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct ContextId(NonZeroU64); + +impl Default for ContextId { + // Allocates a unique ID for a new context. + fn default() -> Self { + // No overflow checking is needed here: overflowing this would take + // thousands of years. + static NEXT_ID: AtomicU64 = AtomicU64::new(1); + Self(NonZeroU64::new(NEXT_ID.fetch_add(1, Ordering::Relaxed)).unwrap()) + } +} + +/// Trait to represent an object managed by a context. This is implemented on +/// the VM types managed by the context. +pub trait ContextObject: Sized { + fn list(ctx: &ContextObjects) -> &Vec; + fn list_mut(ctx: &mut ContextObjects) -> &mut Vec; +} +macro_rules! impl_context_object { + ($($field:ident => $ty:ty,)*) => { + $( + impl ContextObject for $ty { + fn list(ctx: &ContextObjects) -> &Vec { + &ctx.$field + } + fn list_mut(ctx: &mut ContextObjects) -> &mut Vec { + &mut ctx.$field + } + } + )* + }; +} +impl_context_object! { + functions => VMFunction, + tables => VMTable, + globals => VMGlobal, + instances => InstanceHandle, + memories => VMMemory, + extern_objs => VMExternObj, +} + +/// Set of objects managed by a context. +#[derive(Default)] +pub struct ContextObjects { + id: ContextId, + memories: Vec, + tables: Vec, + globals: Vec, + functions: Vec, + instances: Vec, + extern_objs: Vec, +} + +impl ContextObjects { + /// Returns the ID of this context. + pub fn id(&self) -> ContextId { + self.id + } + + /// Returns a pair of mutable references from two handles. + /// + /// Panics if both handles point to the same object. + pub fn get_2_mut( + &mut self, + a: InternalContextHandle, + b: InternalContextHandle, + ) -> (&mut T, &mut T) { + assert_ne!(a.index(), b.index()); + let list = T::list_mut(self); + if a.index() < b.index() { + let (low, high) = list.split_at_mut(b.index()); + (&mut low[a.index()], &mut high[0]) + } else { + let (low, high) = list.split_at_mut(a.index()); + (&mut high[0], &mut low[a.index()]) + } + } +} + +/// Handle to an object managed by a context. +/// +/// Internally this is just an integer index into a context. A reference to the +/// context must be passed in separately to access the actual object. +pub struct ContextHandle { + id: ContextId, + internal: InternalContextHandle, +} + +impl Clone for ContextHandle { + fn clone(&self) -> Self { + Self { + id: self.id, + internal: self.internal, + } + } +} + +impl fmt::Debug for ContextHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ContextHandle") + .field("id", &self.id) + .field("internal", &self.internal.index()) + .finish() + } +} + +impl ContextHandle { + /// Moves the given object into a context and returns a handle to it. + pub fn new(ctx: &mut ContextObjects, val: T) -> Self { + Self { + id: ctx.id, + internal: InternalContextHandle::new(ctx, val), + } + } + + /// Returns a reference to the object that this handle points to. + pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { + assert_eq!(self.id, ctx.id, "object used with the wrong context"); + self.internal.get(ctx) + } + + /// Returns a mutable reference to the object that this handle points to. + pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { + assert_eq!(self.id, ctx.id, "object used with the wrong context"); + self.internal.get_mut(ctx) + } + + /// Returns the internal handle contains within this handle. + pub fn internal_handle(&self) -> InternalContextHandle { + self.internal + } + + /// Returns the ID of the context associated with the handle. + pub fn context_id(&self) -> ContextId { + self.id + } + + /// Constructs a `ContextHandle` from a `ContextId` and an `InternalContextHandle`. + /// + /// # Safety + /// Handling `InternalContextHandle` values is unsafe because they do not track context ID. + pub unsafe fn from_internal(id: ContextId, internal: InternalContextHandle) -> Self { + Self { id, internal } + } +} + +/// Internal handle to an object owned by the current context. +/// +/// Unlike `ContextHandle` this does not track the context ID: it is only +/// intended to be used within objects already owned by a context. +#[repr(transparent)] +pub struct InternalContextHandle { + // Use a NonZero here to reduce the size of Option. + idx: NonZeroUsize, + marker: PhantomData T>, +} + +impl Clone for InternalContextHandle { + fn clone(&self) -> Self { + *self + } +} +impl Copy for InternalContextHandle {} + +impl fmt::Debug for InternalContextHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("InternalContextHandle") + .field("idx", &self.idx) + .finish() + } +} +impl PartialEq for InternalContextHandle { + fn eq(&self, other: &Self) -> bool { + self.idx == other.idx + } +} +impl Eq for InternalContextHandle {} + +impl InternalContextHandle { + /// Moves the given object into a context and returns a handle to it. + pub fn new(ctx: &mut ContextObjects, val: T) -> Self { + let list = T::list_mut(ctx); + let idx = NonZeroUsize::new(list.len() + 1).unwrap(); + list.push(val); + Self { + idx, + marker: PhantomData, + } + } + + /// Returns a reference to the object that this handle points to. + pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { + &T::list(ctx)[self.idx.get() - 1] + } + + /// Returns a mutable reference to the object that this handle points to. + pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { + &mut T::list_mut(ctx)[self.idx.get() - 1] + } + + pub(crate) fn index(&self) -> usize { + self.idx.get() + } + + pub(crate) fn from_index(idx: usize) -> Option { + NonZeroUsize::new(idx).map(|idx| Self { + idx, + marker: PhantomData, + }) + } +} + +/// Data used by the generated code is generally located inline within the +/// `VMContext` for items defined in an instance. Host-defined objects are +/// allocated separately and owned directly by the context. +pub enum MaybeInstanceOwned { + /// The data is owned here. + Host(Box>), + + /// The data is stored inline in the `VMContext` of an instance. + Instance(NonNull), +} + +impl MaybeInstanceOwned { + /// Returns underlying pointer to the VM data. + pub fn as_ptr(&self) -> NonNull { + match self { + MaybeInstanceOwned::Host(p) => unsafe { NonNull::new_unchecked(p.get()) }, + MaybeInstanceOwned::Instance(p) => *p, + } + } +} diff --git a/lib/vm/src/export.rs b/lib/vm/src/export.rs index d50792c5359..b87581cbd7f 100644 --- a/lib/vm/src/export.rs +++ b/lib/vm/src/export.rs @@ -1,39 +1,35 @@ // This file contains code from external sources. // Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md -use crate::global::Global; -use crate::instance::WeakOrStrongInstanceRef; -use crate::memory::Memory; -use crate::table::Table; -use crate::vmcontext::{VMFunctionEnvironment, VMFunctionKind, VMTrampoline}; -use crate::VMFunctionBody; -use std::sync::Arc; -use wasmer_types::{FunctionType, MemoryStyle, MemoryType, TableStyle, TableType}; +use crate::context::InternalContextHandle; +use crate::global::VMGlobal; +use crate::memory::VMMemory; +use crate::table::VMTable; +use crate::vmcontext::VMFunctionKind; +use crate::{MaybeInstanceOwned, VMCallerCheckedAnyfunc}; +use std::any::Any; +use wasmer_types::FunctionType; /// The value of an export passed from one instance to another. -#[derive(Debug)] pub enum VMExtern { /// A function export value. - Function(VMFunction), + Function(InternalContextHandle), /// A table export value. - Table(VMTable), + Table(InternalContextHandle), /// A memory export value. - Memory(VMMemory), + Memory(InternalContextHandle), /// A global export value. - Global(VMGlobal), + Global(InternalContextHandle), } /// A function export value. -#[derive(Clone, Debug, PartialEq)] pub struct VMFunction { - /// The address of the native-code function. - pub address: *const VMFunctionBody, - - /// Pointer to the containing `VMContext`. - pub vmctx: VMFunctionEnvironment, + /// Pointer to the `VMCallerCheckedAnyfunc` which contains data needed to + /// call the function and check its signature. + pub anyfunc: MaybeInstanceOwned, /// The function type, used for compatibility checking. pub signature: FunctionType, @@ -42,194 +38,6 @@ pub struct VMFunction { /// function). pub kind: VMFunctionKind, - /// Address of the function call trampoline owned by the same - /// VMContext that owns the VMFunctionBody. - /// - /// May be `None` when the function is a host function (`FunctionType` - /// == `Dynamic` or `vmctx` == `nullptr`). - pub call_trampoline: Option, - - /// A “reference” to the instance through the - /// `InstanceRef`. `None` if it is a host function. - pub instance_ref: Option, -} - -impl VMFunction { - /// Converts the stored instance ref into a strong `InstanceRef` if it is weak. - /// Returns None if it cannot be upgraded. - pub fn upgrade_instance_ref(&mut self) -> Option<()> { - if let Some(ref mut ir) = self.instance_ref { - *ir = ir.upgrade()?; - } - Some(()) - } -} - -/// # Safety -/// There is no non-threadsafe logic directly in this type. Calling the function -/// may not be threadsafe. -unsafe impl Send for VMFunction {} -/// # Safety -/// The members of an VMFunction are immutable after construction. -unsafe impl Sync for VMFunction {} - -impl From for VMExtern { - fn from(func: VMFunction) -> Self { - Self::Function(func) - } -} - -/// A table export value. -#[derive(Clone, Debug)] -pub struct VMTable { - /// Pointer to the containing `Table`. - pub from: Arc, - - /// A “reference” to the instance through the - /// `InstanceRef`. `None` if it is a host table. - pub instance_ref: Option, -} - -/// # Safety -/// This is correct because there is no non-threadsafe logic directly in this type; -/// correct use of the raw table from multiple threads via `definition` requires `unsafe` -/// and is the responsibilty of the user of this type. -unsafe impl Send for VMTable {} - -/// # Safety -/// This is correct because the values directly in `definition` should be considered immutable -/// and the type is both `Send` and `Clone` (thus marking it `Sync` adds no new behavior, it -/// only makes this type easier to use) -unsafe impl Sync for VMTable {} - -impl VMTable { - /// Get the table type for this exported table - pub fn ty(&self) -> &TableType { - self.from.ty() - } - - /// Get the style for this exported table - pub fn style(&self) -> &TableStyle { - self.from.style() - } - - /// Returns whether or not the two `VMTable`s refer to the same Memory. - pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.from, &other.from) - } - - /// Converts the stored instance ref into a strong `InstanceRef` if it is weak. - /// Returns None if it cannot be upgraded. - pub fn upgrade_instance_ref(&mut self) -> Option<()> { - if let Some(ref mut ir) = self.instance_ref { - *ir = ir.upgrade()?; - } - Some(()) - } -} - -impl From for VMExtern { - fn from(table: VMTable) -> Self { - Self::Table(table) - } -} - -/// A memory export value. -#[derive(Debug, Clone)] -pub struct VMMemory { - /// Pointer to the containing `Memory`. - pub from: Arc, - - /// A “reference” to the instance through the - /// `InstanceRef`. `None` if it is a host memory. - pub instance_ref: Option, -} - -/// # Safety -/// This is correct because there is no non-threadsafe logic directly in this type; -/// correct use of the raw memory from multiple threads via `definition` requires `unsafe` -/// and is the responsibilty of the user of this type. -unsafe impl Send for VMMemory {} - -/// # Safety -/// This is correct because the values directly in `definition` should be considered immutable -/// and the type is both `Send` and `Clone` (thus marking it `Sync` adds no new behavior, it -/// only makes this type easier to use) -unsafe impl Sync for VMMemory {} - -impl VMMemory { - /// Get the type for this exported memory - pub fn ty(&self) -> MemoryType { - self.from.ty() - } - - /// Get the style for this exported memory - pub fn style(&self) -> &MemoryStyle { - self.from.style() - } - - /// Returns whether or not the two `VMMemory`s refer to the same Memory. - pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.from, &other.from) - } - - /// Converts the stored instance ref into a strong `InstanceRef` if it is weak. - /// Returns None if it cannot be upgraded. - pub fn upgrade_instance_ref(&mut self) -> Option<()> { - if let Some(ref mut ir) = self.instance_ref { - *ir = ir.upgrade()?; - } - Some(()) - } -} - -impl From for VMExtern { - fn from(memory: VMMemory) -> Self { - Self::Memory(memory) - } -} - -/// A global export value. -#[derive(Debug, Clone)] -pub struct VMGlobal { - /// The global declaration, used for compatibility checking. - pub from: Arc, - - /// A “reference” to the instance through the - /// `InstanceRef`. `None` if it is a host global. - pub instance_ref: Option, -} - -/// # Safety -/// This is correct because there is no non-threadsafe logic directly in this type; -/// correct use of the raw global from multiple threads via `definition` requires `unsafe` -/// and is the responsibilty of the user of this type. -unsafe impl Send for VMGlobal {} - -/// # Safety -/// This is correct because the values directly in `definition` should be considered immutable -/// from the perspective of users of this type and the type is both `Send` and `Clone` (thus -/// marking it `Sync` adds no new behavior, it only makes this type easier to use) -unsafe impl Sync for VMGlobal {} - -impl VMGlobal { - /// Returns whether or not the two `VMGlobal`s refer to the same Global. - pub fn same(&self, other: &Self) -> bool { - Arc::ptr_eq(&self.from, &other.from) - } - - /// Converts the stored instance ref into a strong `InstanceRef` if it is weak. - /// Returns None if it cannot be upgraded. - pub fn upgrade_instance_ref(&mut self) -> Option<()> { - if let Some(ref mut ir) = self.instance_ref { - *ir = ir.upgrade()?; - } - Some(()) - } -} - -impl From for VMExtern { - fn from(global: VMGlobal) -> Self { - Self::Global(global) - } + /// Associated data owned by a host function. + pub host_data: Box, } diff --git a/lib/vm/src/extern_ref.rs b/lib/vm/src/extern_ref.rs new file mode 100644 index 00000000000..89657a00907 --- /dev/null +++ b/lib/vm/src/extern_ref.rs @@ -0,0 +1,47 @@ +use std::any::Any; + +use wasmer_types::RawValue; + +use crate::context::InternalContextHandle; + +/// Underlying object referenced by a `VMExternRef`. +pub struct VMExternObj { + contents: Box, +} + +impl VMExternObj { + /// Wraps the given value to expose it to Wasm code as an externref. + pub fn new(val: impl Any + Send + Sync + 'static) -> Self { + Self { + contents: Box::new(val), + } + } + + #[allow(clippy::should_implement_trait)] + /// Returns a reference to the underlying value. + pub fn as_ref(&self) -> &(dyn Any + Send + Sync + 'static) { + &*self.contents + } +} + +/// Represents an opaque reference to any data within WebAssembly. +#[repr(transparent)] +#[derive(Debug, Clone, Copy)] +pub struct VMExternRef(pub InternalContextHandle); + +impl VMExternRef { + /// Converts the `VMExternRef` into a `RawValue`. + pub fn into_raw(self) -> RawValue { + RawValue { + funcref: self.0.index(), + } + } + + /// Extracts a `VMExternRef` from a `RawValue`. + /// + /// # Safety + /// `raw` must be a valid `VMExternRef` instance. + pub unsafe fn from_raw(raw: RawValue) -> Option { + InternalContextHandle::from_index(raw.externref).map(Self) + } +} diff --git a/lib/vm/src/func_data_registry.rs b/lib/vm/src/func_data_registry.rs deleted file mode 100644 index ddf4eb7e6b8..00000000000 --- a/lib/vm/src/func_data_registry.rs +++ /dev/null @@ -1,118 +0,0 @@ -//! A registry for `VMFuncRef`s. This allows us to deduplicate funcrefs so that -//! identical `VMCallerCheckedAnyfunc`s will give us identical funcrefs. -//! -//! This registry also helps ensure that the `VMFuncRef`s can stay valid for as -//! long as we need them to. - -use crate::vmcontext::VMCallerCheckedAnyfunc; -use std::collections::HashMap; -use std::sync::Mutex; - -/// The registry that holds the values that `VMFuncRef`s point to. -#[derive(Debug, Default)] -pub struct FuncDataRegistry { - // This structure is stored in an `Engine` and is intended to be shared - // across many instances. Ideally instances can themselves be sent across - // threads, and ideally we can compile across many threads. As a result we - // use interior mutability here with a lock to avoid having callers to - // externally synchronize calls to compilation. - inner: Mutex, -} - -// We use raw pointers but the data never moves, so it's not a problem -unsafe impl Send for FuncDataRegistry {} -unsafe impl Sync for FuncDataRegistry {} - -/// A function reference. A single word that points to metadata about a function. -#[repr(transparent)] -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct VMFuncRef(pub(crate) *const VMCallerCheckedAnyfunc); - -impl wasmer_types::NativeWasmType for VMFuncRef { - const WASM_TYPE: wasmer_types::Type = wasmer_types::Type::FuncRef; - type Abi = Self; - - #[inline] - fn from_abi(abi: Self::Abi) -> Self { - abi - } - - #[inline] - fn into_abi(self) -> Self::Abi { - self - } - - #[inline] - fn to_binary(self) -> i128 { - self.0 as _ - } - - #[inline] - fn from_binary(bits: i128) -> Self { - // TODO: ensure that the safety invariants are actually upheld here - Self(bits as _) - } -} - -impl VMFuncRef { - /// Check if the FuncRef is null - // TODO: make this const when `std::ptr::is_null` is const - pub fn is_null(&self) -> bool { - self.0.is_null() - } - - /// Create a new null FuncRef - pub const fn null() -> Self { - Self(std::ptr::null()) - } -} - -impl std::ops::Deref for VMFuncRef { - type Target = *const VMCallerCheckedAnyfunc; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::ops::DerefMut for VMFuncRef { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -// We use raw pointers but the data never moves, so it's not a problem -// TODO: update docs -unsafe impl Send for VMFuncRef {} -unsafe impl Sync for VMFuncRef {} - -#[derive(Debug, Default)] -struct Inner { - func_data: Vec, - anyfunc_to_index: HashMap, -} - -impl FuncDataRegistry { - /// Create a new `FuncDataRegistry`. - pub fn new() -> Self { - Default::default() - } - - /// Register a signature and return its unique index. - pub fn register(&self, anyfunc: VMCallerCheckedAnyfunc) -> VMFuncRef { - let mut inner = self.inner.lock().unwrap(); - if let Some(&idx) = inner.anyfunc_to_index.get(&anyfunc) { - let data: &_ = &inner.func_data[idx]; - let inner_ptr: &VMCallerCheckedAnyfunc = &*data; - VMFuncRef(inner_ptr) - } else { - let idx = inner.func_data.len(); - inner.func_data.push(anyfunc); - inner.anyfunc_to_index.insert(anyfunc, idx); - - let data: &_ = &inner.func_data[idx]; - let inner_ptr: &VMCallerCheckedAnyfunc = &*data; - VMFuncRef(inner_ptr) - } - } -} diff --git a/lib/vm/src/global.rs b/lib/vm/src/global.rs index 40114bd3435..5dd6f6665ac 100644 --- a/lib/vm/src/global.rs +++ b/lib/vm/src/global.rs @@ -1,53 +1,23 @@ -use crate::vmcontext::VMGlobalDefinition; -use std::cell::UnsafeCell; -use std::ptr::NonNull; -use std::sync::Mutex; -use thiserror::Error; -use wasmer_types::{GlobalType, Mutability, Type, Value, WasmValueType}; +use crate::{context::MaybeInstanceOwned, vmcontext::VMGlobalDefinition}; +use std::{cell::UnsafeCell, ptr::NonNull}; +use wasmer_types::GlobalType; -#[derive(Debug)] /// A Global instance -pub struct Global { +pub struct VMGlobal { ty: GlobalType, - // TODO: this box may be unnecessary - vm_global_definition: Box>, - // used to synchronize gets/sets - lock: Mutex<()>, + vm_global_definition: MaybeInstanceOwned, } -/// # Safety -/// This is safe to send between threads because there is no-thread specific logic. -/// TODO: look into other reasons that make something not `Send` -unsafe impl Send for Global {} -/// # Safety -/// This is safe to share between threads because it uses a `Mutex` internally. -unsafe impl Sync for Global {} - -/// Error type describing things that can go wrong when operating on Wasm Globals. -#[derive(Error, Debug, Clone, PartialEq, Hash)] -pub enum GlobalError { - /// The error returned when attempting to set an immutable global. - #[error("Attempted to set an immutable global")] - ImmutableGlobalCannotBeSet, - - /// The error returned when attempting to operate on a global as a specific type - /// that differs from the global's own type. - #[error("Attempted to operate on a global of type {expected} as a global of type {found}")] - IncorrectType { - /// The type that the global is. - expected: Type, - /// The type that we were asked to use it as. - found: Type, - }, -} - -impl Global { +impl VMGlobal { /// Create a new, zero bit-pattern initialized global from a [`GlobalType`]. pub fn new(global_type: GlobalType) -> Self { Self { ty: global_type, - vm_global_definition: Box::new(UnsafeCell::new(VMGlobalDefinition::new())), - lock: Mutex::new(()), + // TODO: Currently all globals are host-owned, we should inline the + // VMGlobalDefinition in VMContext for instance-defined globals. + vm_global_definition: MaybeInstanceOwned::Host(Box::new(UnsafeCell::new( + VMGlobalDefinition::new(), + ))), } } @@ -58,82 +28,6 @@ impl Global { /// Get a pointer to the underlying definition used by the generated code. pub fn vmglobal(&self) -> NonNull { - let ptr = self.vm_global_definition.as_ref() as *const UnsafeCell - as *const VMGlobalDefinition as *mut VMGlobalDefinition; - unsafe { NonNull::new_unchecked(ptr) } - } - - /// Get a value from the global. - // TODO(reftypes): the `&dyn Any` here for `Store` is a work-around for the fact - // that `Store` is defined in `API` when we need it earlier. Ideally this should - // be removed. - pub fn get(&self, store: &dyn std::any::Any) -> Value { - let _global_guard = self.lock.lock().unwrap(); - unsafe { - let definition = &*self.vm_global_definition.get(); - match self.ty().ty { - Type::I32 => Value::I32(definition.to_i32()), - Type::I64 => Value::I64(definition.to_i64()), - Type::F32 => Value::F32(definition.to_f32()), - Type::F64 => Value::F64(definition.to_f64()), - Type::V128 => Value::V128(definition.to_u128()), - Type::ExternRef => Value::ExternRef(definition.to_externref().into()), - Type::FuncRef => { - let p = definition.to_u128() as i128; - if p as usize == 0 { - Value::FuncRef(None) - } else { - let v = T::read_value_from(store, &p); - Value::FuncRef(Some(v)) - } - } - } - } - } - - /// Set a value for the global. - /// - /// # Safety - /// The caller should check that the `val` comes from the same store as this global. - pub unsafe fn set(&self, val: Value) -> Result<(), GlobalError> { - let _global_guard = self.lock.lock().unwrap(); - if self.ty().mutability != Mutability::Var { - return Err(GlobalError::ImmutableGlobalCannotBeSet); - } - if val.ty() != self.ty().ty { - return Err(GlobalError::IncorrectType { - expected: self.ty.ty, - found: val.ty(), - }); - } - self.set_unchecked(val) - } - - /// Set a value from the global (unchecked) - /// - /// # Safety - /// The caller should check that the `val` comes from the same store as this global. - /// The caller should also ensure that this global is synchronized. Otherwise, use - /// `set` instead. - pub unsafe fn set_unchecked(&self, val: Value) -> Result<(), GlobalError> { - // ideally we'd use atomics for the global value rather than needing to lock it - let definition = &mut *self.vm_global_definition.get(); - match val { - Value::I32(i) => *definition.as_i32_mut() = i, - Value::I64(i) => *definition.as_i64_mut() = i, - Value::F32(f) => *definition.as_f32_mut() = f, - Value::F64(f) => *definition.as_f64_mut() = f, - Value::V128(x) => *definition.as_bytes_mut() = x.to_ne_bytes(), - Value::ExternRef(r) => { - let extern_ref = definition.as_externref_mut(); - extern_ref.ref_drop(); - *extern_ref = r.into() - } - Value::FuncRef(None) => *definition.as_u128_mut() = 0, - Value::FuncRef(Some(r)) => { - r.write_value_to(definition.as_u128_mut() as *mut u128 as *mut i128) - } - } - Ok(()) + self.vm_global_definition.as_ptr() } } diff --git a/lib/vm/src/imports.rs b/lib/vm/src/imports.rs index 22bead4f730..fb5da509907 100644 --- a/lib/vm/src/imports.rs +++ b/lib/vm/src/imports.rs @@ -1,7 +1,6 @@ // This file contains code from external sources. // Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md -use crate::instance::ImportFunctionEnv; use crate::vmcontext::{VMFunctionImport, VMGlobalImport, VMMemoryImport, VMTableImport}; use wasmer_types::entity::{BoxedSlice, PrimaryMap}; use wasmer_types::{FunctionIndex, GlobalIndex, MemoryIndex, TableIndex}; @@ -12,18 +11,6 @@ pub struct Imports { /// Resolved addresses for imported functions. pub functions: BoxedSlice, - /// Initializers for host function environments. This is split out from `functions` - /// because the generated code never needs to touch this and the extra wasted - /// space may affect Wasm runtime performance due to increased cache pressure. - /// - /// We make it optional so that we can free the data after use. - /// - /// We move this data in `get_imported_function_envs` because there's - /// no value to keeping it around; host functions must be initialized - /// exactly once so we save some memory and improve correctness by - /// moving this data. - pub host_function_env_initializers: Option>, - /// Resolved addresses for imported tables. pub tables: BoxedSlice, @@ -38,14 +25,12 @@ impl Imports { /// Construct a new `Imports` instance. pub fn new( function_imports: PrimaryMap, - host_function_env_initializers: PrimaryMap, table_imports: PrimaryMap, memory_imports: PrimaryMap, global_imports: PrimaryMap, ) -> Self { Self { functions: function_imports.into_boxed_slice(), - host_function_env_initializers: Some(host_function_env_initializers.into_boxed_slice()), tables: table_imports.into_boxed_slice(), memories: memory_imports.into_boxed_slice(), globals: global_imports.into_boxed_slice(), @@ -56,21 +41,9 @@ impl Imports { pub fn none() -> Self { Self { functions: PrimaryMap::new().into_boxed_slice(), - host_function_env_initializers: None, tables: PrimaryMap::new().into_boxed_slice(), memories: PrimaryMap::new().into_boxed_slice(), globals: PrimaryMap::new().into_boxed_slice(), } } - - /// Get the `WasmerEnv::init_with_instance` function pointers and the pointers - /// to the envs to call it on. - /// - /// This function can only be called once, it deletes the data it returns after - /// returning it to ensure that it's not called more than once. - pub fn get_imported_function_envs(&mut self) -> BoxedSlice { - self.host_function_env_initializers - .take() - .unwrap_or_else(|| PrimaryMap::new().into_boxed_slice()) - } } diff --git a/lib/vm/src/instance/allocator.rs b/lib/vm/src/instance/allocator.rs index f49b42a14b5..29804c7460e 100644 --- a/lib/vm/src/instance/allocator.rs +++ b/lib/vm/src/instance/allocator.rs @@ -1,11 +1,11 @@ -use super::{Instance, InstanceRef}; +use super::{Instance, InstanceHandle}; use crate::vmcontext::{VMMemoryDefinition, VMTableDefinition}; -use crate::VMOffsets; use std::alloc::{self, Layout}; use std::convert::TryFrom; use std::mem; use std::ptr::{self, NonNull}; use wasmer_types::entity::EntityRef; +use wasmer_types::VMOffsets; use wasmer_types::{LocalMemoryIndex, LocalTableIndex, ModuleInfo}; /// This is an intermediate type that manages the raw allocation and @@ -187,7 +187,7 @@ impl InstanceAllocator { /// Finish preparing by writing the [`Instance`] into memory, and /// consume this `InstanceAllocator`. - pub(crate) fn write_instance(mut self, instance: Instance) -> InstanceRef { + pub(crate) fn write_instance(mut self, instance: Instance) -> InstanceHandle { // Prevent the old state's drop logic from being called as we // transition into the new state. self.consumed = true; @@ -195,7 +195,7 @@ impl InstanceAllocator { unsafe { // `instance` is moved at `Self.instance_ptr`. This // pointer has been allocated by `Self::allocate_instance` - // (so by `InstanceRef::allocate_instance`). + // (so by `InstanceHandle::allocate_instance`). ptr::write(self.instance_ptr.as_ptr(), instance); // Now `instance_ptr` is correctly initialized! } @@ -204,7 +204,10 @@ impl InstanceAllocator { // This is correct because of the invariants of `Self` and // because we write `Instance` to the pointer in this function. - unsafe { InstanceRef::new(instance, instance_layout) } + InstanceHandle { + instance, + instance_layout, + } } /// Get the [`VMOffsets`] for the allocated buffer. diff --git a/lib/vm/src/instance/mod.rs b/lib/vm/src/instance/mod.rs index d9110fb4aa1..43d843fedd6 100644 --- a/lib/vm/src/instance/mod.rs +++ b/lib/vm/src/instance/mod.rs @@ -3,37 +3,31 @@ //! An `Instance` contains all the runtime state used by execution of //! a WebAssembly module (except its callstack and register state). An -//! `InstanceRef` is a wrapper around `Instance` that manages -//! how it is allocated and deallocated. An `InstanceHandle` is a -//! wrapper around an `InstanceRef`. +//! `InstanceHandle` is a wrapper around `Instance` that manages +//! how it is allocated and deallocated. mod allocator; -mod r#ref; - -pub use allocator::InstanceAllocator; -pub use r#ref::{InstanceRef, WeakInstanceRef, WeakOrStrongInstanceRef}; +use crate::context::{ContextObjects, InternalContextHandle}; use crate::export::VMExtern; -use crate::func_data_registry::VMFuncRef; -use crate::global::Global; use crate::imports::Imports; -use crate::memory::{Memory, MemoryError}; -use crate::table::{Table, TableElement}; +use crate::memory::MemoryError; +use crate::table::TableElement; use crate::trap::{catch_traps, Trap, TrapCode, TrapHandler}; use crate::vmcontext::{ VMBuiltinFunctionsArray, VMCallerCheckedAnyfunc, VMContext, VMFunctionEnvironment, VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMTrampoline, }; -use crate::{FunctionBodyPtr, VMFunctionBody, VMOffsets}; -use crate::{VMFunction, VMGlobal, VMMemory, VMTable}; +use crate::{FunctionBodyPtr, MaybeInstanceOwned, VMFunctionBody}; +use crate::{VMFuncRef, VMFunction, VMGlobal, VMMemory, VMTable}; +pub use allocator::InstanceAllocator; use memoffset::offset_of; use more_asserts::assert_lt; -use std::any::Any; +use std::alloc::Layout; use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; -use std::ffi; use std::fmt; use std::mem; use std::ptr::{self, NonNull}; @@ -43,14 +37,9 @@ use wasmer_types::entity::{packed_option::ReservedValue, BoxedSlice, EntityRef, use wasmer_types::{ DataIndex, DataInitializer, ElemIndex, ExportIndex, FunctionIndex, GlobalIndex, GlobalInit, LocalFunctionIndex, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, - ModuleInfo, Pages, SignatureIndex, TableIndex, TableInitializer, + ModuleInfo, Pages, SignatureIndex, TableIndex, TableInitializer, VMOffsets, }; -/// The function pointer to call with data and an [`Instance`] pointer to -/// finish initializing the host env. -pub type ImportInitializerFuncPtr = - fn(*mut ffi::c_void, *const ffi::c_void) -> Result<(), ResultErr>; - /// A WebAssembly instance. /// /// The type is dynamically-sized. Indeed, the `vmctx` field can @@ -62,17 +51,20 @@ pub(crate) struct Instance { /// The `ModuleInfo` this `Instance` was instantiated from. module: Arc, + /// Pointer to the object store of the context owning this instance. + context: *mut ContextObjects, + /// Offsets in the `vmctx` region. offsets: VMOffsets, /// WebAssembly linear memory data. - memories: BoxedSlice>, + memories: BoxedSlice>, /// WebAssembly table data. - tables: BoxedSlice>, + tables: BoxedSlice>, /// WebAssembly global data. - globals: BoxedSlice>, + globals: BoxedSlice>, /// Pointers to functions in executable memory. functions: BoxedSlice, @@ -82,26 +74,19 @@ pub(crate) struct Instance { /// Passive elements in this instantiation. As `elem.drop`s happen, these /// entries get removed. - passive_elements: RefCell>>, + passive_elements: RefCell]>>>, /// Passive data segments from our module. As `data.drop`s happen, entries /// get removed. A missing entry is considered equivalent to an empty slice. passive_data: RefCell>>, /// Mapping of function indices to their func ref backing data. `VMFuncRef`s - /// will point to elements here for functions defined or imported by this - /// instance. - funcrefs: BoxedSlice, - - /// Hosts can store arbitrary per-instance information here. - host_state: Box, + /// will point to elements here for functions defined by this instance. + funcrefs: BoxedSlice, - /// Functions to operate on host environments in the imports - /// and pointers to the environments. - /// - /// TODO: Be sure to test with serialize/deserialize and imported - /// functions from other Wasm modules. - imported_function_envs: BoxedSlice, + /// Mapping of function indices to their func ref backing data. `VMFuncRef`s + /// will point to elements here for functions imported by this instance. + imported_funcrefs: BoxedSlice>, /// Additional context used by compiled WebAssembly code. This /// field is last, and represents a dynamically-sized array that @@ -110,88 +95,6 @@ pub(crate) struct Instance { vmctx: VMContext, } -/// A collection of data about host envs used by imported functions. -#[derive(Debug)] -pub enum ImportFunctionEnv { - /// The `vmctx` pointer does not refer to a host env, there is no - /// metadata about it. - NoEnv, - /// We're dealing with a user-defined host env. - /// - /// This host env may be either unwrapped (the user-supplied host env - /// directly) or wrapped. i.e. in the case of Dynamic functions, we - /// store our own extra data along with the user supplied env, - /// thus the `env` pointer here points to the outermost type. - Env { - /// The function environment. This is not always the user-supplied - /// env. - env: *mut ffi::c_void, - - /// A clone function for duplicating the env. - clone: fn(*mut ffi::c_void) -> *mut ffi::c_void, - /// This field is not always present. When it is present, it - /// should be set to `None` after use to prevent double - /// initialization. - initializer: Option, - /// The destructor to clean up the type in `env`. - /// - /// # Safety - /// - This function must be called ina synchronized way. For - /// example, in the `Drop` implementation of this type. - destructor: unsafe fn(*mut ffi::c_void), - }, -} - -impl ImportFunctionEnv { - /// Get the `initializer` function pointer if it exists. - fn initializer(&self) -> Option { - match self { - Self::Env { initializer, .. } => *initializer, - _ => None, - } - } -} - -impl Clone for ImportFunctionEnv { - fn clone(&self) -> Self { - match &self { - Self::NoEnv => Self::NoEnv, - Self::Env { - env, - clone, - destructor, - initializer, - } => { - let new_env = (*clone)(*env); - Self::Env { - env: new_env, - clone: *clone, - destructor: *destructor, - initializer: *initializer, - } - } - } - } -} - -impl Drop for ImportFunctionEnv { - fn drop(&mut self) { - match self { - Self::Env { - env, destructor, .. - } => { - // # Safety - // - This is correct because we know no other references - // to this data can exist if we're dropping it. - unsafe { - (destructor)(*env); - } - } - Self::NoEnv => (), - } - } -} - impl fmt::Debug for Instance { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.debug_struct("Instance").finish() @@ -216,6 +119,14 @@ impl Instance { &*self.module } + fn context(&self) -> &ContextObjects { + unsafe { &*self.context } + } + + fn context_mut(&mut self) -> &mut ContextObjects { + unsafe { &mut *self.context } + } + /// Offsets in the `vmctx` region. fn offsets(&self) -> &VMOffsets { &self.offsets @@ -232,14 +143,6 @@ impl Instance { unsafe { &*self.imported_functions_ptr().add(index) } } - /// Get the import initializer func at the given index if it exists. - fn imported_function_env_initializer( - &self, - index: FunctionIndex, - ) -> Option { - self.imported_function_envs[index].initializer() - } - /// Return a pointer to the `VMFunctionImport`s. fn imported_functions_ptr(&self) -> *mut VMFunctionImport { unsafe { self.vmctx_plus_offset(self.offsets.vmctx_imported_functions_begin()) } @@ -377,12 +280,6 @@ impl Instance { self.vmctx() as *const VMContext as *mut VMContext } - /// Return a reference to the custom state attached to this instance. - #[inline] - pub fn host_state(&self) -> &dyn Any { - &*self.host_state - } - /// Invoke the WebAssembly start function of the instance, if one is present. fn invoke_start_function( &self, @@ -459,18 +356,18 @@ impl Instance { /// Returns `None` if memory can't be grown by the specified amount /// of pages. pub(crate) fn memory_grow( - &self, + &mut self, memory_index: LocalMemoryIndex, delta: IntoPages, ) -> Result where IntoPages: Into, { - let mem = self + let mem = *self .memories .get(memory_index) .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index())); - mem.grow(delta.into()) + mem.get_mut(self.context_mut()).grow(delta.into()) } /// Grow imported memory by the specified amount of pages. @@ -482,7 +379,7 @@ impl Instance { /// This and `imported_memory_size` are currently unsafe because they /// dereference the memory import's pointers. pub(crate) unsafe fn imported_memory_grow( - &self, + &mut self, memory_index: MemoryIndex, delta: IntoPages, ) -> Result @@ -490,16 +387,17 @@ impl Instance { IntoPages: Into, { let import = self.imported_memory(memory_index); - let from = import.from.as_ref(); - from.grow(delta.into()) + let mem = import.handle; + mem.get_mut(self.context_mut()).grow(delta.into()) } /// Returns the number of allocated wasm pages. pub(crate) fn memory_size(&self, memory_index: LocalMemoryIndex) -> Pages { - self.memories + let mem = *self + .memories .get(memory_index) - .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index())) - .size() + .unwrap_or_else(|| panic!("no memory for index {}", memory_index.index())); + mem.get(self.context()).size() } /// Returns the number of allocated wasm pages in an imported memory. @@ -509,16 +407,17 @@ impl Instance { /// dereference the memory import's pointers. pub(crate) unsafe fn imported_memory_size(&self, memory_index: MemoryIndex) -> Pages { let import = self.imported_memory(memory_index); - let from = import.from.as_ref(); - from.size() + let mem = import.handle; + mem.get(self.context()).size() } /// Returns the number of elements in a given table. pub(crate) fn table_size(&self, table_index: LocalTableIndex) -> u32 { - self.tables + let table = self + .tables .get(table_index) - .unwrap_or_else(|| panic!("no table for index {}", table_index.index())) - .size() + .unwrap_or_else(|| panic!("no table for index {}", table_index.index())); + table.get(self.context()).size() } /// Returns the number of elements in a given imported table. @@ -527,8 +426,8 @@ impl Instance { /// `table_index` must be a valid, imported table index. pub(crate) unsafe fn imported_table_size(&self, table_index: TableIndex) -> u32 { let import = self.imported_table(table_index); - let from = import.from.as_ref(); - from.size() + let table = import.handle; + table.get(self.context()).size() } /// Grow table by the specified amount of elements. @@ -536,18 +435,16 @@ impl Instance { /// Returns `None` if table can't be grown by the specified amount /// of elements. pub(crate) fn table_grow( - &self, + &mut self, table_index: LocalTableIndex, delta: u32, init_value: TableElement, ) -> Option { - let result = self + let table = *self .tables .get(table_index) - .unwrap_or_else(|| panic!("no table for index {}", table_index.index())) - .grow(delta, init_value); - - result + .unwrap_or_else(|| panic!("no table for index {}", table_index.index())); + table.get_mut(self.context_mut()).grow(delta, init_value) } /// Grow table by the specified amount of elements. @@ -555,14 +452,14 @@ impl Instance { /// # Safety /// `table_index` must be a valid, imported table index. pub(crate) unsafe fn imported_table_grow( - &self, + &mut self, table_index: TableIndex, delta: u32, init_value: TableElement, ) -> Option { let import = self.imported_table(table_index); - let from = import.from.as_ref(); - from.grow(delta, init_value) + let table = import.handle; + table.get_mut(self.context_mut()).grow(delta, init_value) } /// Get table element by index. @@ -571,10 +468,11 @@ impl Instance { table_index: LocalTableIndex, index: u32, ) -> Option { - self.tables + let table = self + .tables .get(table_index) - .unwrap_or_else(|| panic!("no table for index {}", table_index.index())) - .get(index) + .unwrap_or_else(|| panic!("no table for index {}", table_index.index())); + table.get(self.context()).get(index) } /// Returns the element at the given index. @@ -587,21 +485,22 @@ impl Instance { index: u32, ) -> Option { let import = self.imported_table(table_index); - let from = import.from.as_ref(); - from.get(index) + let table = import.handle; + table.get(self.context()).get(index) } /// Set table element by index. pub(crate) fn table_set( - &self, + &mut self, table_index: LocalTableIndex, index: u32, val: TableElement, ) -> Result<(), Trap> { - self.tables + let table = *self + .tables .get(table_index) - .unwrap_or_else(|| panic!("no table for index {}", table_index.index())) - .set(index, val) + .unwrap_or_else(|| panic!("no table for index {}", table_index.index())); + table.get_mut(self.context_mut()).set(index, val) } /// Set table element by index for an imported table. @@ -609,26 +508,27 @@ impl Instance { /// # Safety /// `table_index` must be a valid, imported table index. pub(crate) unsafe fn imported_table_set( - &self, + &mut self, table_index: TableIndex, index: u32, val: TableElement, ) -> Result<(), Trap> { let import = self.imported_table(table_index); - let from = import.from.as_ref(); - from.set(index, val) - } - - pub(crate) fn func_ref(&self, function_index: FunctionIndex) -> Option { - Some(self.get_vm_funcref(function_index)) + let table = import.handle; + table.get_mut(self.context_mut()).set(index, val) } /// Get a `VMFuncRef` for the given `FunctionIndex`. - fn get_vm_funcref(&self, index: FunctionIndex) -> VMFuncRef { - if index == FunctionIndex::reserved_value() { - return VMFuncRef::null(); + pub(crate) fn func_ref(&self, function_index: FunctionIndex) -> Option { + if function_index == FunctionIndex::reserved_value() { + None + } else if let Some(local_function_index) = self.module.local_func_index(function_index) { + Some(VMFuncRef(NonNull::from( + &self.funcrefs[local_function_index], + ))) + } else { + Some(VMFuncRef(self.imported_funcrefs[function_index])) } - VMFuncRef(&self.funcrefs[index]) } /// The `table.init` operation: initializes a portion of a table with a @@ -639,7 +539,7 @@ impl Instance { /// Returns a `Trap` error when the range within the table is out of bounds /// or the range within the passive element is out of bounds. pub(crate) fn table_init( - &self, + &mut self, table_index: TableIndex, elem_index: ElemIndex, dst: u32, @@ -648,11 +548,12 @@ impl Instance { ) -> Result<(), Trap> { // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-init - let table = self.get_table(table_index); + let table = self.get_table_handle(table_index); + let table = unsafe { table.get_mut(&mut *self.context) }; let passive_elements = self.passive_elements.borrow(); let elem = passive_elements .get(&elem_index) - .map_or::<&[VMFuncRef], _>(&[], |e| &**e); + .map_or::<&[Option], _>(&[], |e| &**e); if src .checked_add(len) @@ -677,7 +578,7 @@ impl Instance { /// /// Returns a `Trap` error when the range within the table is out of bounds pub(crate) fn table_fill( - &self, + &mut self, table_index: TableIndex, start_index: u32, item: TableElement, @@ -833,7 +734,7 @@ impl Instance { /// Get a table by index regardless of whether it is locally-defined or an /// imported, foreign table. - pub(crate) fn get_table(&self, table_index: TableIndex) -> &dyn Table { + pub(crate) fn get_table(&mut self, table_index: TableIndex) -> &mut VMTable { if let Some(local_table_index) = self.module.local_table_index(table_index) { self.get_local_table(local_table_index) } else { @@ -842,26 +743,51 @@ impl Instance { } /// Get a locally-defined table. - pub(crate) fn get_local_table(&self, index: LocalTableIndex) -> &dyn Table { - self.tables[index].as_ref() + pub(crate) fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable { + let table = self.tables[index]; + table.get_mut(self.context_mut()) } /// Get an imported, foreign table. - pub(crate) fn get_foreign_table(&self, index: TableIndex) -> &dyn Table { + pub(crate) fn get_foreign_table(&mut self, index: TableIndex) -> &mut VMTable { let import = self.imported_table(index); - &*import.from + let table = import.handle; + table.get_mut(self.context_mut()) + } + + /// Get a table handle by index regardless of whether it is locally-defined + /// or an imported, foreign table. + pub(crate) fn get_table_handle( + &mut self, + table_index: TableIndex, + ) -> InternalContextHandle { + if let Some(local_table_index) = self.module.local_table_index(table_index) { + self.tables[local_table_index] + } else { + self.imported_table(table_index).handle + } } } -/// A handle holding an `InstanceRef`, which holds an `Instance` -/// of a WebAssembly module. +/// A handle holding an `Instance` of a WebAssembly module. /// /// This is more or less a public facade of the private `Instance`, /// providing useful higher-level API. #[derive(Debug, Clone, PartialEq)] pub struct InstanceHandle { - /// The [`InstanceRef`]. See its documentation to learn more. - instance: InstanceRef, + /// The layout of `Instance` (which can vary). + instance_layout: Layout, + + /// The `Instance` itself. + /// + /// `Instance` must not be dropped manually by Rust, because it's + /// allocated manually with `alloc` and a specific layout (Rust + /// would be able to drop `Instance` itself but it will imply a + /// memory leak because of `alloc`). + /// + /// No one in the code has a copy of the `Instance`'s + /// pointer. `Self` is the only one. + instance: NonNull, } impl InstanceHandle { @@ -890,19 +816,18 @@ impl InstanceHandle { pub unsafe fn new( allocator: InstanceAllocator, module: Arc, + context: &mut ContextObjects, finished_functions: BoxedSlice, finished_function_call_trampolines: BoxedSlice, - finished_memories: BoxedSlice>, - finished_tables: BoxedSlice>, - finished_globals: BoxedSlice>, + finished_memories: BoxedSlice>, + finished_tables: BoxedSlice>, + finished_globals: BoxedSlice>, imports: Imports, vmshared_signatures: BoxedSlice, - host_state: Box, - imported_function_envs: BoxedSlice, ) -> Result { let vmctx_globals = finished_globals .values() - .map(|m| m.vmglobal()) + .map(|m| m.get(context).vmglobal()) .collect::>() .into_boxed_slice(); let passive_data = RefCell::new(module.passive_data.clone()); @@ -911,9 +836,11 @@ impl InstanceHandle { let offsets = allocator.offsets().clone(); // use dummy value to create an instance so we can get the vmctx pointer let funcrefs = PrimaryMap::new().into_boxed_slice(); + let imported_funcrefs = PrimaryMap::new().into_boxed_slice(); // Create the `Instance`. The unique, the One. let instance = Instance { module, + context, offsets, memories: finished_memories, tables: finished_tables, @@ -922,32 +849,31 @@ impl InstanceHandle { function_call_trampolines: finished_function_call_trampolines, passive_elements: Default::default(), passive_data, - host_state, funcrefs, - imported_function_envs, + imported_funcrefs, vmctx: VMContext {}, }; - let mut instance_ref = allocator.write_instance(instance); + let mut instance_handle = allocator.write_instance(instance); // Set the funcrefs after we've built the instance { - let instance = instance_ref.as_mut().unwrap(); + let instance = instance_handle.instance_mut(); let vmctx_ptr = instance.vmctx_ptr(); - instance.funcrefs = build_funcrefs( + (instance.funcrefs, instance.imported_funcrefs) = build_funcrefs( &*instance.module, + context, &imports, &instance.functions, &vmshared_signatures, + &instance.function_call_trampolines, vmctx_ptr, ); } - Self { - instance: instance_ref, - } + instance_handle }; - let instance = handle.instance().as_ref(); + let instance = handle.instance(); ptr::copy( vmshared_signatures.values().as_slice().as_ptr(), @@ -996,8 +922,13 @@ impl InstanceHandle { } /// Return a reference to the contained `Instance`. - pub(crate) fn instance(&self) -> &InstanceRef { - &self.instance + pub(crate) fn instance(&self) -> &Instance { + unsafe { self.instance.as_ref() } + } + + /// Return a mutable reference to the contained `Instance`. + pub(crate) fn instance_mut(&mut self) -> &mut Instance { + unsafe { self.instance.as_mut() } } /// Finishes the instantiation process started by `Instance::new`. @@ -1006,11 +937,11 @@ impl InstanceHandle { /// /// Only safe to call immediately after instantiation. pub unsafe fn finish_instantiation( - &self, + &mut self, trap_handler: &(dyn TrapHandler + 'static), data_initializers: &[DataInitializer<'_>], ) -> Result<(), Trap> { - let instance = self.instance().as_ref(); + let instance = self.instance_mut(); // Apply the initializers. initialize_tables(instance)?; @@ -1024,118 +955,95 @@ impl InstanceHandle { /// Return a reference to the vmctx used by compiled wasm code. pub fn vmctx(&self) -> &VMContext { - self.instance().as_ref().vmctx() + self.instance().vmctx() } /// Return a raw pointer to the vmctx used by compiled wasm code. pub fn vmctx_ptr(&self) -> *mut VMContext { - self.instance().as_ref().vmctx_ptr() + self.instance().vmctx_ptr() } /// Return a reference to the `VMOffsets` to get offsets in the /// `Self::vmctx_ptr` region. Be careful when doing pointer /// arithmetic! pub fn vmoffsets(&self) -> &VMOffsets { - self.instance().as_ref().offsets() + self.instance().offsets() } /// Return a reference-counting pointer to a module. pub fn module(&self) -> &Arc { - self.instance().as_ref().module() + self.instance().module() } /// Return a reference to a module. pub fn module_ref(&self) -> &ModuleInfo { - self.instance().as_ref().module_ref() + self.instance().module_ref() } /// Lookup an export with the given name. - pub fn lookup(&self, field: &str) -> Option { - let export = self.module_ref().exports.get(field)?; + pub fn lookup(&mut self, field: &str) -> Option { + let export = *self.module_ref().exports.get(field)?; Some(self.lookup_by_declaration(export)) } /// Lookup an export with the given export declaration. - // TODO: maybe EngineExport - pub fn lookup_by_declaration(&self, export: &ExportIndex) -> VMExtern { - let instance = self.instance().clone(); - let instance_ref = instance.as_ref(); + pub fn lookup_by_declaration(&mut self, export: ExportIndex) -> VMExtern { + let instance = self.instance(); match export { ExportIndex::Function(index) => { - let sig_index = &instance_ref.module.functions[*index]; - let (address, vmctx, _function_ptr) = - if let Some(def_index) = instance_ref.module.local_func_index(*index) { - ( - instance_ref.functions[def_index].0 as *const _, - VMFunctionEnvironment { - vmctx: instance_ref.vmctx_ptr(), - }, - None, - ) - } else { - let import = instance_ref.imported_function(*index); - let initializer = instance_ref.imported_function_env_initializer(*index); - (import.body, import.environment, initializer) + let sig_index = &instance.module.functions[index]; + let handle = if let Some(def_index) = instance.module.local_func_index(index) { + // A VMFunction is lazily created only for functions that are + // exported. + let signature = instance.module.signatures[*sig_index].clone(); + let vm_function = VMFunction { + anyfunc: MaybeInstanceOwned::Instance(NonNull::from( + &instance.funcrefs[def_index], + )), + signature, + // Any function received is already static at this point as: + // 1. All locally defined functions in the Wasm have a static signature. + // 2. All the imported functions are already static (because + // they point to the trampolines rather than the dynamic addresses). + kind: VMFunctionKind::Static, + host_data: Box::new(()), }; - let call_trampoline = Some(instance_ref.function_call_trampolines[*sig_index]); - let signature = instance_ref.module.signatures[*sig_index].clone(); - - VMFunction { - address, - // Any function received is already static at this point as: - // 1. All locally defined functions in the Wasm have a static signature. - // 2. All the imported functions are already static (because - // they point to the trampolines rather than the dynamic addresses). - kind: VMFunctionKind::Static, - signature, - vmctx, - call_trampoline, - instance_ref: Some(WeakOrStrongInstanceRef::Strong(instance)), - } - .into() + InternalContextHandle::new(self.instance_mut().context_mut(), vm_function) + } else { + let import = instance.imported_function(index); + import.handle + }; + + VMExtern::Function(handle) } ExportIndex::Table(index) => { - let from = if let Some(def_index) = instance_ref.module.local_table_index(*index) { - instance_ref.tables[def_index].clone() + let handle = if let Some(def_index) = instance.module.local_table_index(index) { + instance.tables[def_index] } else { - let import = instance_ref.imported_table(*index); - import.from.clone() + let import = instance.imported_table(index); + import.handle }; - VMTable { - from, - instance_ref: Some(WeakOrStrongInstanceRef::Strong(instance)), - } - .into() + VMExtern::Table(handle) } ExportIndex::Memory(index) => { - let from = if let Some(def_index) = instance_ref.module.local_memory_index(*index) { - instance_ref.memories[def_index].clone() + let handle = if let Some(def_index) = instance.module.local_memory_index(index) { + instance.memories[def_index] } else { - let import = instance_ref.imported_memory(*index); - import.from.clone() + let import = instance.imported_memory(index); + import.handle }; - VMMemory { - from, - instance_ref: Some(WeakOrStrongInstanceRef::Strong(instance)), - } - .into() + VMExtern::Memory(handle) } ExportIndex::Global(index) => { - let from = { - if let Some(def_index) = instance_ref.module.local_global_index(*index) { - instance_ref.globals[def_index].clone() - } else { - let import = instance_ref.imported_global(*index); - import.from.clone() - } + let handle = if let Some(def_index) = instance.module.local_global_index(index) { + instance.globals[def_index] + } else { + let import = instance.imported_global(index); + import.handle }; - VMGlobal { - from, - instance_ref: Some(WeakOrStrongInstanceRef::Strong(instance)), - } - .into() + VMExtern::Global(handle) } } } @@ -1149,14 +1057,9 @@ impl InstanceHandle { self.module().exports.iter() } - /// Return a reference to the custom state attached to this instance. - pub fn host_state(&self) -> &dyn Any { - self.instance().as_ref().host_state() - } - /// Return the memory index for the given `VMMemoryDefinition` in this instance. pub fn memory_index(&self, memory: &VMMemoryDefinition) -> LocalMemoryIndex { - self.instance().as_ref().memory_index(memory) + self.instance().memory_index(memory) } /// Grow memory in this instance by the specified amount of pages. @@ -1164,19 +1067,19 @@ impl InstanceHandle { /// Returns `None` if memory can't be grown by the specified amount /// of pages. pub fn memory_grow( - &self, + &mut self, memory_index: LocalMemoryIndex, delta: IntoPages, ) -> Result where IntoPages: Into, { - self.instance().as_ref().memory_grow(memory_index, delta) + self.instance_mut().memory_grow(memory_index, delta) } /// Return the table index for the given `VMTableDefinition` in this instance. pub fn table_index(&self, table: &VMTableDefinition) -> LocalTableIndex { - self.instance().as_ref().table_index(table) + self.instance().table_index(table) } /// Grow table in this instance by the specified amount of pages. @@ -1184,13 +1087,12 @@ impl InstanceHandle { /// Returns `None` if memory can't be grown by the specified amount /// of pages. pub fn table_grow( - &self, + &mut self, table_index: LocalTableIndex, delta: u32, init_value: TableElement, ) -> Option { - self.instance() - .as_ref() + self.instance_mut() .table_grow(table_index, delta, init_value) } @@ -1198,60 +1100,24 @@ impl InstanceHandle { /// /// Returns `None` if index is out of bounds. pub fn table_get(&self, table_index: LocalTableIndex, index: u32) -> Option { - self.instance().as_ref().table_get(table_index, index) + self.instance().table_get(table_index, index) } /// Set table element reference. /// /// Returns an error if the index is out of bounds pub fn table_set( - &self, + &mut self, table_index: LocalTableIndex, index: u32, val: TableElement, ) -> Result<(), Trap> { - self.instance().as_ref().table_set(table_index, index, val) + self.instance_mut().table_set(table_index, index, val) } /// Get a table defined locally within this module. - pub fn get_local_table(&self, index: LocalTableIndex) -> &dyn Table { - self.instance().as_ref().get_local_table(index) - } - - /// Initializes the host environments. - /// - /// # Safety - /// - This function must be called with the correct `Err` type parameter: the error type is not - /// visible to code in `wasmer_vm`, so it's the caller's responsibility to ensure these - /// functions are called with the correct type. - /// - `instance_ptr` must point to a valid `wasmer::Instance`. - pub unsafe fn initialize_host_envs( - &mut self, - instance_ptr: *const ffi::c_void, - ) -> Result<(), Err> { - let instance_ref = self.instance.as_mut_unchecked(); - - for import_function_env in instance_ref.imported_function_envs.values_mut() { - match import_function_env { - ImportFunctionEnv::Env { - env, - ref mut initializer, - .. - } => { - if let Some(f) = initializer { - // transmute our function pointer into one with the correct error type - let f = mem::transmute::< - &ImportInitializerFuncPtr, - &ImportInitializerFuncPtr, - >(f); - f(*env, instance_ptr)?; - } - *initializer = None; - } - ImportFunctionEnv::NoEnv => (), - } - } - Ok(()) + pub fn get_local_table(&mut self, index: LocalTableIndex) -> &mut VMTable { + self.instance_mut().get_local_table(index) } } @@ -1262,9 +1128,9 @@ fn get_memory_init_start(init: &DataInitializer<'_>, instance: &Instance) -> usi if let Some(base) = init.location.base { let val = unsafe { if let Some(def_index) = instance.module.local_global_index(base) { - instance.global(def_index).to_u32() + instance.global(def_index).val.u32 } else { - instance.imported_global(base).definition.as_ref().to_u32() + instance.imported_global(base).definition.as_ref().val.u32 } }; start += usize::try_from(val).unwrap(); @@ -1298,9 +1164,9 @@ fn get_table_init_start(init: &TableInitializer, instance: &Instance) -> usize { if let Some(base) = init.base { let val = unsafe { if let Some(def_index) = instance.module.local_global_index(base) { - instance.global(def_index).to_u32() + instance.global(def_index).val.u32 } else { - instance.imported_global(base).definition.as_ref().to_u32() + instance.imported_global(base).definition.as_ref().val.u32 } }; start += usize::try_from(val).unwrap(); @@ -1310,11 +1176,12 @@ fn get_table_init_start(init: &TableInitializer, instance: &Instance) -> usize { } /// Initialize the table memory from the provided initializers. -fn initialize_tables(instance: &Instance) -> Result<(), Trap> { +fn initialize_tables(instance: &mut Instance) -> Result<(), Trap> { let module = Arc::clone(&instance.module); for init in &module.table_initializers { let start = get_table_init_start(init, instance); - let table = instance.get_table(init.table_index); + let table = instance.get_table_handle(init.table_index); + let table = unsafe { table.get_mut(&mut *instance.context) }; if start .checked_add(init.elements.len()) @@ -1324,7 +1191,7 @@ fn initialize_tables(instance: &Instance) -> Result<(), Trap> { } for (i, func_idx) in init.elements.iter().enumerate() { - let anyfunc = instance.get_vm_funcref(*func_idx); + let anyfunc = instance.func_ref(*func_idx); table .set( u32::try_from(start + i).unwrap(), @@ -1356,10 +1223,7 @@ fn initialize_passive_elements(instance: &Instance) { .map(|(idx, segments)| { ( *idx, - segments - .iter() - .map(|s| instance.get_vm_funcref(*s)) - .collect(), + segments.iter().map(|s| instance.func_ref(*s)).collect(), ) }), ); @@ -1367,7 +1231,7 @@ fn initialize_passive_elements(instance: &Instance) { /// Initialize the table memory from the provided initializers. fn initialize_memories( - instance: &Instance, + instance: &mut Instance, data_initializers: &[DataInitializer<'_>], ) -> Result<(), Trap> { for init in data_initializers { @@ -1398,11 +1262,11 @@ fn initialize_globals(instance: &Instance) { unsafe { let to = instance.global_ptr(index).as_ptr(); match initializer { - GlobalInit::I32Const(x) => *(*to).as_i32_mut() = *x, - GlobalInit::I64Const(x) => *(*to).as_i64_mut() = *x, - GlobalInit::F32Const(x) => *(*to).as_f32_mut() = *x, - GlobalInit::F64Const(x) => *(*to).as_f64_mut() = *x, - GlobalInit::V128Const(x) => *(*to).as_bytes_mut() = *x.bytes(), + GlobalInit::I32Const(x) => (*to).val.i32 = *x, + GlobalInit::I64Const(x) => (*to).val.i64 = *x, + GlobalInit::F32Const(x) => (*to).val.f32 = *x, + GlobalInit::F64Const(x) => (*to).val.f64 = *x, + GlobalInit::V128Const(x) => (*to).val.bytes = *x.bytes(), GlobalInit::GetGlobal(x) => { let from: VMGlobalDefinition = if let Some(def_x) = module.local_global_index(*x) { @@ -1412,10 +1276,10 @@ fn initialize_globals(instance: &Instance) { }; *to = from; } - GlobalInit::RefNullConst => *(*to).as_funcref_mut() = VMFuncRef::null(), + GlobalInit::RefNullConst => (*to).val.funcref = 0, GlobalInit::RefFunc(func_idx) => { let funcref = instance.func_ref(*func_idx).unwrap(); - *(*to).as_funcref_mut() = funcref; + (*to).val = funcref.into_raw(); } } } @@ -1426,23 +1290,23 @@ fn initialize_globals(instance: &Instance) { /// future funcref operations are just looking up this data. fn build_funcrefs( module_info: &ModuleInfo, + ctx: &ContextObjects, imports: &Imports, finished_functions: &BoxedSlice, vmshared_signatures: &BoxedSlice, + function_call_trampolines: &BoxedSlice, vmctx_ptr: *mut VMContext, -) -> BoxedSlice { - let mut func_refs = PrimaryMap::with_capacity(module_info.functions.len()); +) -> ( + BoxedSlice, + BoxedSlice>, +) { + let mut func_refs = + PrimaryMap::with_capacity(module_info.functions.len() - module_info.num_imported_functions); + let mut imported_func_refs = PrimaryMap::with_capacity(module_info.num_imported_functions); // do imported functions - for (index, import) in imports.functions.iter() { - let sig_index = module_info.functions[index]; - let type_index = vmshared_signatures[sig_index]; - let anyfunc = VMCallerCheckedAnyfunc { - func_ptr: import.body, - type_index, - vmctx: import.environment, - }; - func_refs.push(anyfunc); + for import in imports.functions.values() { + imported_func_refs.push(import.handle.get(ctx).anyfunc.as_ptr()); } // do local functions @@ -1450,13 +1314,17 @@ fn build_funcrefs( let index = module_info.func_index(local_index); let sig_index = module_info.functions[index]; let type_index = vmshared_signatures[sig_index]; + let call_trampoline = function_call_trampolines[sig_index]; let anyfunc = VMCallerCheckedAnyfunc { func_ptr: func_ptr.0, type_index, vmctx: VMFunctionEnvironment { vmctx: vmctx_ptr }, + call_trampoline, }; func_refs.push(anyfunc); } - - func_refs.into_boxed_slice() + ( + func_refs.into_boxed_slice(), + imported_func_refs.into_boxed_slice(), + ) } diff --git a/lib/vm/src/instance/ref.rs b/lib/vm/src/instance/ref.rs index fa8a1a2b6aa..6d8b7c57898 100644 --- a/lib/vm/src/instance/ref.rs +++ b/lib/vm/src/instance/ref.rs @@ -131,101 +131,4 @@ impl InstanceRef { pub(super) fn as_mut(&mut self) -> Option<&mut Instance> { Some(Arc::get_mut(&mut self.0)?.as_mut()) } - - /// Like [`InstanceRef::as_mut`] but always succeeds. - /// May cause undefined behavior if used improperly. - /// - /// # Safety - /// It is the caller's responsibility to ensure exclusivity and synchronization of the - /// instance before calling this function. No other pointers to any Instance data - /// should be dereferenced for the lifetime of the returned `&mut Instance`. - #[inline] - pub(super) unsafe fn as_mut_unchecked(&mut self) -> &mut Instance { - let ptr: *mut InstanceInner = Arc::as_ptr(&self.0) as *mut _; - (&mut *ptr).as_mut() - } -} - -/// A weak instance ref. This type does not keep the underlying `Instance` alive -/// but can be converted into a full `InstanceRef` if the underlying `Instance` hasn't -/// been deallocated. -#[derive(Debug, Clone)] -pub struct WeakInstanceRef(Weak); - -impl PartialEq for WeakInstanceRef { - fn eq(&self, other: &Self) -> bool { - self.0.ptr_eq(&other.0) - } -} - -impl WeakInstanceRef { - /// Try to convert into a strong, `InstanceRef`. - pub fn upgrade(&self) -> Option { - let inner = self.0.upgrade()?; - Some(InstanceRef(inner)) - } -} - -/// An `InstanceRef` that may or may not be keeping the `Instance` alive. -/// -/// This type is useful for types that conditionally must keep / not keep the -/// underlying `Instance` alive. For example, to prevent cycles in `WasmerEnv`s. -#[derive(Debug, Clone, PartialEq)] -pub enum WeakOrStrongInstanceRef { - /// A weak instance ref. - Weak(WeakInstanceRef), - /// A strong instance ref. - Strong(InstanceRef), -} - -impl WeakOrStrongInstanceRef { - /// Tries to upgrade weak references to a strong reference, returning None - /// if it can't be done. - pub fn upgrade(&self) -> Option { - match self { - Self::Weak(weak) => weak.upgrade().map(Self::Strong), - Self::Strong(strong) => Some(Self::Strong(strong.clone())), - } - } - - /// Clones self into a weak reference. - pub fn downgrade(&self) -> Self { - match self { - Self::Weak(weak) => Self::Weak(weak.clone()), - Self::Strong(strong) => Self::Weak(WeakInstanceRef(Arc::downgrade(&strong.0))), - } - } -} - -impl TryFrom for InstanceRef { - type Error = &'static str; - fn try_from(value: WeakOrStrongInstanceRef) -> Result { - match value { - WeakOrStrongInstanceRef::Strong(strong) => Ok(strong), - WeakOrStrongInstanceRef::Weak(weak) => { - weak.upgrade().ok_or("Failed to upgrade weak reference") - } - } - } -} - -impl From for WeakInstanceRef { - fn from(value: WeakOrStrongInstanceRef) -> Self { - match value { - WeakOrStrongInstanceRef::Strong(strong) => Self(Arc::downgrade(&strong.0)), - WeakOrStrongInstanceRef::Weak(weak) => weak, - } - } -} - -impl From for WeakOrStrongInstanceRef { - fn from(value: WeakInstanceRef) -> Self { - Self::Weak(value) - } -} - -impl From for WeakOrStrongInstanceRef { - fn from(value: InstanceRef) -> Self { - Self::Strong(value) - } } diff --git a/lib/vm/src/lib.rs b/lib/vm/src/lib.rs index 1e5edd2d79f..835b27bdd29 100644 --- a/lib/vm/src/lib.rs +++ b/lib/vm/src/lib.rs @@ -20,8 +20,9 @@ ) )] +mod context; mod export; -mod func_data_registry; +mod extern_ref; mod global; mod imports; mod instance; @@ -35,19 +36,21 @@ mod vmcontext; pub mod libcalls; +use std::ptr::NonNull; + +pub use crate::context::{ + ContextHandle, ContextId, ContextObjects, InternalContextHandle, MaybeInstanceOwned, +}; pub use crate::export::*; -pub use crate::func_data_registry::{FuncDataRegistry, VMFuncRef}; +pub use crate::extern_ref::{VMExternObj, VMExternRef}; pub use crate::global::*; pub use crate::imports::Imports; -pub use crate::instance::{ - ImportFunctionEnv, ImportInitializerFuncPtr, InstanceAllocator, InstanceHandle, - WeakOrStrongInstanceRef, -}; -pub use crate::memory::{LinearMemory, Memory, MemoryError}; +pub use crate::instance::{InstanceAllocator, InstanceHandle}; +pub use crate::memory::{MemoryError, VMMemory}; pub use crate::mmap::Mmap; pub use crate::probestack::PROBESTACK; pub use crate::sig_registry::SignatureRegistry; -pub use crate::table::{LinearTable, Table, TableElement}; +pub use crate::table::{TableElement, VMTable}; pub use crate::trap::*; pub use crate::vmcontext::{ VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionEnvironment, @@ -56,8 +59,8 @@ pub use crate::vmcontext::{ }; pub use wasmer_types::LibCall; pub use wasmer_types::MemoryStyle; +use wasmer_types::RawValue; pub use wasmer_types::TableStyle; -pub use wasmer_types::VMExternRef; pub use wasmer_types::{TargetSharedSignatureIndex, VMBuiltinFunctionIndex, VMOffsets}; #[deprecated( @@ -121,3 +124,25 @@ unsafe impl Send for FunctionBodyPtr {} /// The VMFunctionBody that this points to is opaque, so there's no data to /// read or write through this pointer. This is essentially a usize. unsafe impl Sync for FunctionBodyPtr {} + +/// A function reference. A single word that points to metadata about a function. +#[repr(transparent)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct VMFuncRef(pub NonNull); + +impl VMFuncRef { + /// Converts the `VMFuncRef` into a `RawValue`. + pub fn into_raw(self) -> RawValue { + RawValue { + funcref: self.0.as_ptr() as usize, + } + } + + /// Extracts a `VMFuncRef` from a `RawValue`. + /// + /// # Safety + /// `raw.funcref` must be a valid pointer. + pub unsafe fn from_raw(raw: RawValue) -> Option { + NonNull::new(raw.funcref as *mut VMCallerCheckedAnyfunc).map(Self) + } +} diff --git a/lib/vm/src/libcalls.rs b/lib/vm/src/libcalls.rs index fbeb27a3c02..f9b1b28709d 100644 --- a/lib/vm/src/libcalls.rs +++ b/lib/vm/src/libcalls.rs @@ -37,12 +37,11 @@ #![allow(missing_docs)] // For some reason lint fails saying that `LibCall` is not documented, when it actually is -use crate::func_data_registry::VMFuncRef; -use crate::on_host_stack; use crate::probestack::PROBESTACK; use crate::table::{RawTableElement, TableElement}; use crate::trap::{raise_lib_trap, Trap, TrapCode}; use crate::vmcontext::VMContext; +use crate::{on_host_stack, VMFuncRef}; pub use wasmer_types::LibCall; use wasmer_types::{ DataIndex, ElemIndex, FunctionIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, @@ -151,7 +150,7 @@ pub unsafe extern "C" fn wasmer_vm_memory32_grow( memory_index: u32, ) -> u32 { on_host_stack(|| { - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let memory_index = LocalMemoryIndex::from_u32(memory_index); instance @@ -173,7 +172,7 @@ pub unsafe extern "C" fn wasmer_vm_imported_memory32_grow( memory_index: u32, ) -> u32 { on_host_stack(|| { - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let memory_index = MemoryIndex::from_u32(memory_index); instance @@ -229,10 +228,14 @@ pub unsafe extern "C" fn wasmer_vm_table_copy( let result = { let dst_table_index = TableIndex::from_u32(dst_table_index); let src_table_index = TableIndex::from_u32(src_table_index); - let instance = (&*vmctx).instance(); - let dst_table = instance.get_table(dst_table_index); - let src_table = instance.get_table(src_table_index); - dst_table.copy(src_table, dst, src, len) + if dst_table_index == src_table_index { + let table = (*vmctx).instance_mut().get_table(dst_table_index); + table.copy_within(dst, src, len) + } else { + let dst_table = (*vmctx).instance_mut().get_table(dst_table_index); + let src_table = (*vmctx).instance_mut().get_table(src_table_index); + dst_table.copy(src_table, dst, src, len) + } }; if let Err(trap) = result { raise_lib_trap(trap); @@ -256,7 +259,7 @@ pub unsafe extern "C" fn wasmer_vm_table_init( let result = { let table_index = TableIndex::from_u32(table_index); let elem_index = ElemIndex::from_u32(elem_index); - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); instance.table_init(table_index, elem_index, dst, src, len) }; if let Err(trap) = result { @@ -279,9 +282,9 @@ pub unsafe extern "C" fn wasmer_vm_table_fill( ) { let result = { let table_index = TableIndex::from_u32(table_index); - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let elem = match instance.get_table(table_index).ty().ty { - Type::ExternRef => TableElement::ExternRef(item.extern_ref.into()), + Type::ExternRef => TableElement::ExternRef(item.extern_ref), Type::FuncRef => TableElement::FuncRef(item.func_ref), _ => panic!("Unrecognized table type: does not contain references"), }; @@ -354,7 +357,7 @@ pub unsafe extern "C" fn wasmer_vm_imported_table_get( table_index: u32, elem_index: u32, ) -> RawTableElement { - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let table_index = TableIndex::from_u32(table_index); // TODO: type checking, maybe have specialized accessors @@ -379,7 +382,7 @@ pub unsafe extern "C" fn wasmer_vm_table_set( elem_index: u32, value: RawTableElement, ) { - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let table_index = TableIndex::from_u32(table_index); let table_index = instance .module_ref() @@ -387,7 +390,7 @@ pub unsafe extern "C" fn wasmer_vm_table_set( .unwrap(); let elem = match instance.get_local_table(table_index).ty().ty { - Type::ExternRef => TableElement::ExternRef(value.extern_ref.into()), + Type::ExternRef => TableElement::ExternRef(value.extern_ref), Type::FuncRef => TableElement::FuncRef(value.func_ref), _ => panic!("Unrecognized table type: does not contain references"), }; @@ -412,10 +415,10 @@ pub unsafe extern "C" fn wasmer_vm_imported_table_set( elem_index: u32, value: RawTableElement, ) { - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let table_index = TableIndex::from_u32(table_index); let elem = match instance.get_table(table_index).ty().ty { - Type::ExternRef => TableElement::ExternRef(value.extern_ref.into()), + Type::ExternRef => TableElement::ExternRef(value.extern_ref), Type::FuncRef => TableElement::FuncRef(value.func_ref), _ => panic!("Unrecognized table type: does not contain references"), }; @@ -440,11 +443,11 @@ pub unsafe extern "C" fn wasmer_vm_table_grow( table_index: u32, ) -> u32 { on_host_stack(|| { - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let table_index = LocalTableIndex::from_u32(table_index); let init_value = match instance.get_local_table(table_index).ty().ty { - Type::ExternRef => TableElement::ExternRef(init_value.extern_ref.into()), + Type::ExternRef => TableElement::ExternRef(init_value.extern_ref), Type::FuncRef => TableElement::FuncRef(init_value.func_ref), _ => panic!("Unrecognized table type: does not contain references"), }; @@ -468,10 +471,10 @@ pub unsafe extern "C" fn wasmer_vm_imported_table_grow( table_index: u32, ) -> u32 { on_host_stack(|| { - let instance = (&*vmctx).instance(); + let instance = (*vmctx).instance_mut(); let table_index = TableIndex::from_u32(table_index); let init_value = match instance.get_table(table_index).ty().ty { - Type::ExternRef => TableElement::ExternRef(init_value.extern_ref.into()), + Type::ExternRef => TableElement::ExternRef(init_value.extern_ref), Type::FuncRef => TableElement::FuncRef(init_value.func_ref), _ => panic!("Unrecognized table type: does not contain references"), }; diff --git a/lib/vm/src/memory.rs b/lib/vm/src/memory.rs index b10a15e9a35..52afdb90b04 100644 --- a/lib/vm/src/memory.rs +++ b/lib/vm/src/memory.rs @@ -3,17 +3,14 @@ //! Memory management for linear memories. //! -//! `LinearMemory` is to WebAssembly linear memories what `Table` is to WebAssembly tables. +//! `Memory` is to WebAssembly linear memories what `Table` is to WebAssembly tables. -use crate::mmap::Mmap; use crate::vmcontext::VMMemoryDefinition; +use crate::{context::MaybeInstanceOwned, mmap::Mmap}; use more_asserts::assert_ge; -use std::borrow::BorrowMut; use std::cell::UnsafeCell; use std::convert::TryInto; -use std::fmt; use std::ptr::NonNull; -use std::sync::Mutex; use thiserror::Error; use wasmer_types::{Bytes, MemoryStyle, MemoryType, Pages}; @@ -59,31 +56,10 @@ pub enum MemoryError { Generic(String), } -/// Trait for implementing Wasm Memory used by Wasmer. -pub trait Memory: fmt::Debug + Send + Sync { - /// Returns the memory type for this memory. - fn ty(&self) -> MemoryType; - - /// Returns the memory style for this memory. - fn style(&self) -> &MemoryStyle; - - /// Returns the number of allocated wasm pages. - fn size(&self) -> Pages; - - /// Grow memory by the specified amount of wasm pages. - fn grow(&self, delta: Pages) -> Result; - - /// Return a [`VMMemoryDefinition`] for exposing the memory to compiled wasm code. - /// - /// The pointer returned in [`VMMemoryDefinition`] must be valid for the lifetime of this memory. - fn vmmemory(&self) -> NonNull; -} - /// A linear memory instance. -#[derive(Debug)] -pub struct LinearMemory { +pub struct VMMemory { // The underlying allocation. - mmap: Mutex, + mmap: WasmMmap, // The optional maximum size in wasm pages of this linear memory. maximum: Option, @@ -99,34 +75,9 @@ pub struct LinearMemory { offset_guard_size: usize, /// The owned memory definition used by the generated code - vm_memory_definition: VMMemoryDefinitionOwnership, + vm_memory_definition: MaybeInstanceOwned, } -/// A type to help manage who is responsible for the backing memory of them -/// `VMMemoryDefinition`. -#[derive(Debug)] -enum VMMemoryDefinitionOwnership { - /// The `VMMemoryDefinition` is owned by the `Instance` and we should use - /// its memory. This is how a local memory that's exported should be stored. - VMOwned(NonNull), - /// The `VMMemoryDefinition` is owned by the host and we should manage its - /// memory. This is how an imported memory that doesn't come from another - /// Wasm module should be stored. - HostOwned(Box>), -} - -/// We must implement this because of `VMMemoryDefinitionOwnership::VMOwned`. -/// This is correct because synchronization of memory accesses is controlled -/// by the VM. -// REVIEW: I don't believe ^; this probably shouldn't be `Send`... -// mutations from other threads into this data could be a problem, but we probably -// don't want to use atomics for this in the generated code. -// TODO: -unsafe impl Send for LinearMemory {} - -/// This is correct because all internal mutability is protected by a mutex. -unsafe impl Sync for LinearMemory {} - #[derive(Debug)] struct WasmMmap { // Our OS allocation of mmap'd memory. @@ -135,10 +86,10 @@ struct WasmMmap { size: Pages, } -impl LinearMemory { +impl VMMemory { /// Create a new linear memory instance with specified minimum and maximum number of wasm pages. /// - /// This creates a `LinearMemory` with owned metadata: this can be used to create a memory + /// This creates a `Memory` with owned metadata: this can be used to create a memory /// that will be imported into Wasm modules. pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result { unsafe { Self::new_internal(memory, style, None) } @@ -146,7 +97,7 @@ impl LinearMemory { /// Create a new linear memory instance with specified minimum and maximum number of wasm pages. /// - /// This creates a `LinearMemory` with metadata owned by a VM, pointed to by + /// This creates a `Memory` with metadata owned by a VM, pointed to by /// `vm_memory_location`: this can be used to create a local memory. /// /// # Safety @@ -159,7 +110,7 @@ impl LinearMemory { Self::new_internal(memory, style, Some(vm_memory_location)) } - /// Build a `LinearMemory` with either self-owned or VM owned metadata. + /// Build a `Memory` with either self-owned or VM owned metadata. unsafe fn new_internal( memory: &MemoryType, style: &MemoryStyle, @@ -212,7 +163,7 @@ impl LinearMemory { let base_ptr = mmap.alloc.as_mut_ptr(); let mem_length = memory.minimum.bytes().0; Ok(Self { - mmap: Mutex::new(mmap), + mmap, maximum: memory.maximum, offset_guard_size: offset_guard_bytes, vm_memory_definition: if let Some(mem_loc) = vm_memory_location { @@ -222,14 +173,12 @@ impl LinearMemory { md.base = base_ptr; md.current_length = mem_length; } - VMMemoryDefinitionOwnership::VMOwned(mem_loc) + MaybeInstanceOwned::Instance(mem_loc) } else { - VMMemoryDefinitionOwnership::HostOwned(Box::new(UnsafeCell::new( - VMMemoryDefinition { - base: base_ptr, - current_length: mem_length, - }, - ))) + MaybeInstanceOwned::Host(Box::new(UnsafeCell::new(VMMemoryDefinition { + base: base_ptr, + current_length: mem_length, + }))) }, memory: *memory, style: style.clone(), @@ -237,23 +186,12 @@ impl LinearMemory { } /// Get the `VMMemoryDefinition`. - /// - /// # Safety - /// - You must ensure that you have mutually exclusive access before calling - /// this function. You can get this by locking the `mmap` mutex. - unsafe fn get_vm_memory_definition(&self) -> NonNull { - match &self.vm_memory_definition { - VMMemoryDefinitionOwnership::VMOwned(ptr) => *ptr, - VMMemoryDefinitionOwnership::HostOwned(boxed_ptr) => { - NonNull::new_unchecked(boxed_ptr.get()) - } - } + fn get_vm_memory_definition(&self) -> NonNull { + self.vm_memory_definition.as_ptr() } -} -impl Memory for LinearMemory { /// Returns the type for this memory. - fn ty(&self) -> MemoryType { + pub fn ty(&self) -> MemoryType { let minimum = self.size(); let mut out = self.memory; out.minimum = minimum; @@ -262,12 +200,12 @@ impl Memory for LinearMemory { } /// Returns the memory style for this memory. - fn style(&self) -> &MemoryStyle { + pub fn style(&self) -> &MemoryStyle { &self.style } /// Returns the number of allocated wasm pages. - fn size(&self) -> Pages { + pub fn size(&self) -> Pages { // TODO: investigate this function for race conditions unsafe { let md_ptr = self.get_vm_memory_definition(); @@ -280,27 +218,26 @@ impl Memory for LinearMemory { /// /// Returns `None` if memory can't be grown by the specified amount /// of wasm pages. - fn grow(&self, delta: Pages) -> Result { - let mut mmap_guard = self.mmap.lock().unwrap(); - let mmap = mmap_guard.borrow_mut(); + pub fn grow(&mut self, delta: Pages) -> Result { // Optimization of memory.grow 0 calls. if delta.0 == 0 { - return Ok(mmap.size); + return Ok(self.mmap.size); } - let new_pages = mmap + let new_pages = self + .mmap .size .checked_add(delta) .ok_or(MemoryError::CouldNotGrow { - current: mmap.size, + current: self.mmap.size, attempted_delta: delta, })?; - let prev_pages = mmap.size; + let prev_pages = self.mmap.size; if let Some(maximum) = self.maximum { if new_pages > maximum { return Err(MemoryError::CouldNotGrow { - current: mmap.size, + current: self.mmap.size, attempted_delta: delta, }); } @@ -312,7 +249,7 @@ impl Memory for LinearMemory { if new_pages >= Pages::max_value() { // Linear memory size would exceed the index range. return Err(MemoryError::CouldNotGrow { - current: mmap.size, + current: self.mmap.size, attempted_delta: delta, }); } @@ -321,7 +258,7 @@ impl Memory for LinearMemory { let prev_bytes = prev_pages.bytes().0; let new_bytes = new_pages.bytes().0; - if new_bytes > mmap.alloc.len() - self.offset_guard_size { + if new_bytes > self.mmap.alloc.len() - self.offset_guard_size { // If the new size is within the declared maximum, but needs more memory than we // have on hand, it's a dynamic heap and it can move. let guard_bytes = self.offset_guard_size; @@ -336,33 +273,34 @@ impl Memory for LinearMemory { let mut new_mmap = Mmap::accessible_reserved(new_bytes, request_bytes).map_err(MemoryError::Region)?; - let copy_len = mmap.alloc.len() - self.offset_guard_size; - new_mmap.as_mut_slice()[..copy_len].copy_from_slice(&mmap.alloc.as_slice()[..copy_len]); + let copy_len = self.mmap.alloc.len() - self.offset_guard_size; + new_mmap.as_mut_slice()[..copy_len] + .copy_from_slice(&self.mmap.alloc.as_slice()[..copy_len]); - mmap.alloc = new_mmap; + self.mmap.alloc = new_mmap; } else if delta_bytes > 0 { // Make the newly allocated pages accessible. - mmap.alloc + self.mmap + .alloc .make_accessible(prev_bytes, delta_bytes) .map_err(MemoryError::Region)?; } - mmap.size = new_pages; + self.mmap.size = new_pages; // update memory definition unsafe { let mut md_ptr = self.get_vm_memory_definition(); let md = md_ptr.as_mut(); md.current_length = new_pages.bytes().0; - md.base = mmap.alloc.as_mut_ptr() as _; + md.base = self.mmap.alloc.as_mut_ptr() as _; } Ok(prev_pages) } /// Return a `VMMemoryDefinition` for exposing the memory to compiled wasm code. - fn vmmemory(&self) -> NonNull { - let _mmap_guard = self.mmap.lock().unwrap(); - unsafe { self.get_vm_memory_definition() } + pub fn vmmemory(&self) -> NonNull { + self.get_vm_memory_definition() } } diff --git a/lib/vm/src/table.rs b/lib/vm/src/table.rs index b6b00685644..1a8965c32ee 100644 --- a/lib/vm/src/table.rs +++ b/lib/vm/src/table.rs @@ -3,116 +3,33 @@ //! Memory management for tables. //! -//! `Table` is to WebAssembly tables what `LinearMemory` is to WebAssembly linear memories. +//! `Table` is to WebAssembly tables what `Memory` is to WebAssembly linear memories. -use crate::func_data_registry::VMFuncRef; +use crate::context::MaybeInstanceOwned; use crate::vmcontext::VMTableDefinition; use crate::Trap; use crate::VMExternRef; -use std::borrow::{Borrow, BorrowMut}; +use crate::VMFuncRef; use std::cell::UnsafeCell; use std::convert::TryFrom; use std::fmt; use std::ptr::NonNull; -use std::sync::Mutex; -use wasmer_types::{ExternRef, TableStyle, TableType, TrapCode, Type as ValType}; - -/// Trait for implementing the interface of a Wasm table. -pub trait Table: fmt::Debug + Send + Sync { - /// Returns the style for this Table. - fn style(&self) -> &TableStyle; - - /// Returns the type for this Table. - fn ty(&self) -> &TableType; - - /// Returns the number of allocated elements. - fn size(&self) -> u32; - - /// Grow table by the specified amount of elements. - /// - /// Returns `None` if table can't be grown by the specified amount - /// of elements, otherwise returns the previous size of the table. - fn grow(&self, delta: u32, init_value: TableElement) -> Option; - - /// Get reference to the specified element. - /// - /// Returns `None` if the index is out of bounds. - fn get(&self, index: u32) -> Option; - - /// Set reference to the specified element. - /// - /// # Errors - /// - /// Returns an error if the index is out of bounds. - fn set(&self, index: u32, reference: TableElement) -> Result<(), Trap>; - - /// Return a `VMTableDefinition` for exposing the table to compiled wasm code. - fn vmtable(&self) -> NonNull; - - /// Copy `len` elements from `src_table[src_index..]` into `dst_table[dst_index..]`. - /// - /// # Errors - /// - /// Returns an error if the range is out of bounds of either the source or - /// destination tables. - fn copy( - &self, - src_table: &dyn Table, - dst_index: u32, - src_index: u32, - len: u32, - ) -> Result<(), Trap> { - // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-copy - - if src_index - .checked_add(len) - .map_or(true, |n| n > src_table.size()) - { - return Err(Trap::lib(TrapCode::TableAccessOutOfBounds)); - } - - if dst_index.checked_add(len).map_or(true, |m| m > self.size()) { - return Err(Trap::lib(TrapCode::TableAccessOutOfBounds)); - } - - let srcs = src_index..src_index + len; - let dsts = dst_index..dst_index + len; - - // Note on the unwraps: the bounds check above means that these will - // never panic. - // - // TODO: investigate replacing this get/set loop with a `memcpy`. - if dst_index <= src_index { - for (s, d) in (srcs).zip(dsts) { - self.set(d, src_table.get(s).unwrap())?; - } - } else { - for (s, d) in srcs.rev().zip(dsts.rev()) { - self.set(d, src_table.get(s).unwrap())?; - } - } - - Ok(()) - } -} +use wasmer_types::TableStyle; +use wasmer_types::{TableType, TrapCode, Type as ValType}; /// A reference stored in a table. Can be either an externref or a funcref. #[derive(Debug, Clone)] pub enum TableElement { /// Opaque pointer to arbitrary host data. - // Note: we use `ExternRef` instead of `VMExternRef` here to ensure that we don't - // leak by not dec-refing on failure types. - ExternRef(ExternRef), + ExternRef(Option), /// Pointer to function: contains enough information to call it. - FuncRef(VMFuncRef), + FuncRef(Option), } impl From for RawTableElement { fn from(other: TableElement) -> Self { match other { - TableElement::ExternRef(extern_ref) => Self { - extern_ref: extern_ref.into(), - }, + TableElement::ExternRef(extern_ref) => Self { extern_ref }, TableElement::FuncRef(func_ref) => Self { func_ref }, } } @@ -121,8 +38,8 @@ impl From for RawTableElement { #[repr(C)] #[derive(Clone, Copy)] pub union RawTableElement { - pub(crate) extern_ref: VMExternRef, - pub(crate) func_ref: VMFuncRef, + pub(crate) extern_ref: Option, + pub(crate) func_ref: Option, } #[cfg(test)] @@ -141,53 +58,31 @@ impl fmt::Debug for RawTableElement { impl Default for RawTableElement { fn default() -> Self { - Self { - func_ref: VMFuncRef::null(), - } + Self { func_ref: None } } } impl Default for TableElement { fn default() -> Self { - Self::FuncRef(VMFuncRef::null()) + Self::FuncRef(None) } } /// A table instance. -#[derive(Debug)] -pub struct LinearTable { - // TODO: we can remove the mutex by using atomic swaps and preallocating the max table size - vec: Mutex>, +pub struct VMTable { + vec: Vec, maximum: Option, /// The WebAssembly table description. table: TableType, /// Our chosen implementation style. style: TableStyle, - vm_table_definition: VMTableDefinitionOwnership, + vm_table_definition: MaybeInstanceOwned, } -/// A type to help manage who is responsible for the backing table of the -/// `VMTableDefinition`. -#[derive(Debug)] -enum VMTableDefinitionOwnership { - /// The `VMTableDefinition` is owned by the `Instance` and we should use - /// its table. This is how a local table that's exported should be stored. - VMOwned(NonNull), - /// The `VMTableDefinition` is owned by the host and we should manage its - /// table. This is how an imported table that doesn't come from another - /// Wasm module should be stored. - HostOwned(Box>), -} - -/// This is correct because there is no thread-specific data tied to this type. -unsafe impl Send for LinearTable {} -/// This is correct because all internal mutability is protected by a mutex. -unsafe impl Sync for LinearTable {} - -impl LinearTable { +impl VMTable { /// Create a new linear table instance with specified minimum and maximum number of elements. /// - /// This creates a `LinearTable` with metadata owned by a VM, pointed to by + /// This creates a `Table` with metadata owned by a VM, pointed to by /// `vm_table_location`: this can be used to create a local table. pub fn new(table: &TableType, style: &TableStyle) -> Result { unsafe { Self::new_inner(table, style, None) } @@ -195,7 +90,7 @@ impl LinearTable { /// Create a new linear table instance with specified minimum and maximum number of elements. /// - /// This creates a `LinearTable` with metadata owned by a VM, pointed to by + /// This creates a `Table` with metadata owned by a VM, pointed to by /// `vm_table_location`: this can be used to create a local table. /// /// # Safety @@ -208,7 +103,7 @@ impl LinearTable { Self::new_inner(table, style, Some(vm_table_location)) } - /// Create a new `LinearTable` with either self-owned or VM owned metadata. + /// Create a new `Table` with either self-owned or VM owned metadata. unsafe fn new_inner( table: &TableType, style: &TableStyle, @@ -237,7 +132,7 @@ impl LinearTable { let base = vec.as_mut_ptr(); match style { TableStyle::CallerChecksSignature => Ok(Self { - vec: Mutex::new(vec), + vec, maximum: table.maximum, table: *table, style: style.clone(), @@ -248,47 +143,34 @@ impl LinearTable { td.base = base as _; td.current_elements = table_minimum as _; } - VMTableDefinitionOwnership::VMOwned(table_loc) + MaybeInstanceOwned::Instance(table_loc) } else { - VMTableDefinitionOwnership::HostOwned(Box::new(UnsafeCell::new( - VMTableDefinition { - base: base as _, - current_elements: table_minimum as _, - }, - ))) + MaybeInstanceOwned::Host(Box::new(UnsafeCell::new(VMTableDefinition { + base: base as _, + current_elements: table_minimum as _, + }))) }, }), } } /// Get the `VMTableDefinition`. - /// - /// # Safety - /// - You must ensure that you have mutually exclusive access before calling - /// this function. You can get this by locking the `vec` mutex. - unsafe fn get_vm_table_definition(&self) -> NonNull { - match &self.vm_table_definition { - VMTableDefinitionOwnership::VMOwned(ptr) => *ptr, - VMTableDefinitionOwnership::HostOwned(boxed_ptr) => { - NonNull::new_unchecked(boxed_ptr.get()) - } - } + fn get_vm_table_definition(&self) -> NonNull { + self.vm_table_definition.as_ptr() } -} -impl Table for LinearTable { /// Returns the type for this Table. - fn ty(&self) -> &TableType { + pub fn ty(&self) -> &TableType { &self.table } /// Returns the style for this Table. - fn style(&self) -> &TableStyle { + pub fn style(&self) -> &TableStyle { &self.style } /// Returns the number of allocated elements. - fn size(&self) -> u32 { + pub fn size(&self) -> u32 { // TODO: investigate this function for race conditions unsafe { let td_ptr = self.get_vm_table_definition(); @@ -301,9 +183,7 @@ impl Table for LinearTable { /// /// Returns `None` if table can't be grown by the specified amount /// of elements, otherwise returns the previous size of the table. - fn grow(&self, delta: u32, init_value: TableElement) -> Option { - let mut vec_guard = self.vec.lock().unwrap(); - let vec = vec_guard.borrow_mut(); + pub fn grow(&mut self, delta: u32, init_value: TableElement) -> Option { let size = self.size(); let new_len = size.checked_add(delta)?; if self.maximum.map_or(false, |max| new_len > max) { @@ -314,29 +194,15 @@ impl Table for LinearTable { return Some(size); } - // Update the ref count - let element = match init_value { - TableElement::ExternRef(extern_ref) => { - let extern_ref: VMExternRef = extern_ref.into(); - - // We reduce the amount we increment by because `into` prevents - // dropping `init_value` (which is a caller-inc'd ref). - if let Some(val) = (new_len as usize).checked_sub(size as usize + 1) { - extern_ref.ref_inc_by(val) - } - RawTableElement { extern_ref } - } - TableElement::FuncRef(func_ref) => RawTableElement { func_ref }, - }; - - vec.resize(usize::try_from(new_len).unwrap(), element); + self.vec + .resize(usize::try_from(new_len).unwrap(), init_value.into()); // update table definition unsafe { let mut td_ptr = self.get_vm_table_definition(); let td = td_ptr.as_mut(); td.current_elements = new_len; - td.base = vec.as_mut_ptr() as _; + td.base = self.vec.as_mut_ptr() as _; } Some(size) } @@ -344,13 +210,10 @@ impl Table for LinearTable { /// Get reference to the specified element. /// /// Returns `None` if the index is out of bounds. - fn get(&self, index: u32) -> Option { - let vec_guard = self.vec.lock().unwrap(); - let raw_data = vec_guard.borrow().get(index as usize).cloned()?; + pub fn get(&self, index: u32) -> Option { + let raw_data = self.vec.get(index as usize).cloned()?; Some(match self.table.ty { - ValType::ExternRef => { - TableElement::ExternRef(unsafe { raw_data.extern_ref.ref_clone() }.into()) - } + ValType::ExternRef => TableElement::ExternRef(unsafe { raw_data.extern_ref }), ValType::FuncRef => TableElement::FuncRef(unsafe { raw_data.func_ref }), _ => todo!("getting invalid type from table, handle this error"), }) @@ -361,23 +224,15 @@ impl Table for LinearTable { /// # Errors /// /// Returns an error if the index is out of bounds. - fn set(&self, index: u32, reference: TableElement) -> Result<(), Trap> { - let mut vec_guard = self.vec.lock().unwrap(); - let vec = vec_guard.borrow_mut(); - match vec.get_mut(index as usize) { + pub fn set(&mut self, index: u32, reference: TableElement) -> Result<(), Trap> { + match self.vec.get_mut(index as usize) { Some(slot) => { match (self.table.ty, reference) { - (ValType::ExternRef, TableElement::ExternRef(extern_ref)) => { - let extern_ref = extern_ref.into(); - unsafe { - let elem = &mut *slot; - elem.extern_ref.ref_drop(); - elem.extern_ref = extern_ref - } - } - (ValType::FuncRef, r @ TableElement::FuncRef(_)) => { - let element_data = r.into(); - *slot = element_data; + ( + ValType::ExternRef, + r @ TableElement::ExternRef(_) | r @ TableElement::FuncRef(_), + ) => { + *slot = r.into(); } // This path should never be hit by the generated code due to Wasm // validation. @@ -396,8 +251,90 @@ impl Table for LinearTable { } /// Return a `VMTableDefinition` for exposing the table to compiled wasm code. - fn vmtable(&self) -> NonNull { - let _vec_guard = self.vec.lock().unwrap(); - unsafe { self.get_vm_table_definition() } + pub fn vmtable(&self) -> NonNull { + self.get_vm_table_definition() + } + + /// Copy `len` elements from `src_table[src_index..]` into `dst_table[dst_index..]`. + /// + /// # Errors + /// + /// Returns an error if the range is out of bounds of either the source or + /// destination tables. + pub fn copy( + &mut self, + src_table: &Self, + dst_index: u32, + src_index: u32, + len: u32, + ) -> Result<(), Trap> { + // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-copy + + if src_index + .checked_add(len) + .map_or(true, |n| n > src_table.size()) + { + return Err(Trap::lib(TrapCode::TableAccessOutOfBounds)); + } + + if dst_index.checked_add(len).map_or(true, |m| m > self.size()) { + return Err(Trap::lib(TrapCode::TableAccessOutOfBounds)); + } + + let srcs = src_index..src_index + len; + let dsts = dst_index..dst_index + len; + + // Note on the unwraps: the bounds check above means that these will + // never panic. + // + // TODO: investigate replacing this get/set loop with a `memcpy`. + if dst_index <= src_index { + for (s, d) in (srcs).zip(dsts) { + self.set(d, src_table.get(s).unwrap())?; + } + } else { + for (s, d) in srcs.rev().zip(dsts.rev()) { + self.set(d, src_table.get(s).unwrap())?; + } + } + + Ok(()) + } + + /// Copy `len` elements from `table[src_index..]` to `table[dst_index..]`. + /// + /// # Errors + /// + /// Returns an error if the range is out of bounds of either the source or + /// destination tables. + pub fn copy_within(&mut self, dst_index: u32, src_index: u32, len: u32) -> Result<(), Trap> { + // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-copy + + if src_index.checked_add(len).map_or(true, |n| n > self.size()) { + return Err(Trap::lib(TrapCode::TableAccessOutOfBounds)); + } + + if dst_index.checked_add(len).map_or(true, |m| m > self.size()) { + return Err(Trap::lib(TrapCode::TableAccessOutOfBounds)); + } + + let srcs = src_index..src_index + len; + let dsts = dst_index..dst_index + len; + + // Note on the unwraps: the bounds check above means that these will + // never panic. + // + // TODO: investigate replacing this get/set loop with a `memcpy`. + if dst_index <= src_index { + for (s, d) in (srcs).zip(dsts) { + self.set(d, self.get(s).unwrap())?; + } + } else { + for (s, d) in srcs.rev().zip(dsts.rev()) { + self.set(d, self.get(s).unwrap())?; + } + } + + Ok(()) } } diff --git a/lib/vm/src/vmcontext.rs b/lib/vm/src/vmcontext.rs index 80f27a37d44..158e6ca5913 100644 --- a/lib/vm/src/vmcontext.rs +++ b/lib/vm/src/vmcontext.rs @@ -4,21 +4,18 @@ //! This file declares `VMContext` and several related structs which contain //! fields that compiled wasm code accesses directly. -use crate::func_data_registry::VMFuncRef; -use crate::global::Global; +use crate::context::InternalContextHandle; +use crate::global::VMGlobal; use crate::instance::Instance; -use crate::memory::Memory; -use crate::table::Table; +use crate::memory::VMMemory; use crate::trap::{Trap, TrapCode}; -use crate::VMBuiltinFunctionIndex; -use crate::VMExternRef; use crate::VMFunctionBody; -use std::any::Any; +use crate::VMTable; +use crate::{VMBuiltinFunctionIndex, VMFunction}; use std::convert::TryFrom; -use std::fmt; use std::ptr::{self, NonNull}; -use std::sync::Arc; use std::u32; +use wasmer_types::RawValue; /// Union representing the first parameter passed when calling a function. /// @@ -70,15 +67,18 @@ pub struct VMFunctionImport { /// A pointer to the `VMContext` that owns the function or host env data. pub environment: VMFunctionEnvironment, + + /// Handle to the `VMFunction` in the context. + pub handle: InternalContextHandle, } #[cfg(test)] mod test_vmfunction_import { use super::VMFunctionImport; - use crate::VMOffsets; use memoffset::offset_of; use std::mem::size_of; use wasmer_types::ModuleInfo; + use wasmer_types::VMOffsets; #[test] fn check_vmfunction_import_offsets() { @@ -108,7 +108,7 @@ mod test_vmfunction_import { /// containing the relevant context for running the function indicated /// in `address`. #[repr(C)] -pub struct VMDynamicFunctionContext { +pub struct VMDynamicFunctionContext { /// The address of the inner dynamic function. /// /// Note: The function must be on the form of @@ -184,14 +184,14 @@ pub enum VMFunctionKind { /// The fields compiled code needs to access to utilize a WebAssembly table /// imported from another instance. -#[derive(Debug, Clone)] +#[derive(Clone)] #[repr(C)] pub struct VMTableImport { /// A pointer to the imported table description. pub definition: NonNull, - /// A pointer to the `Table` that owns the table description. - pub from: Arc, + /// Handle to the `VMTable` in the context. + pub handle: InternalContextHandle, } #[cfg(test)] @@ -214,23 +214,19 @@ mod test_vmtable_import { offset_of!(VMTableImport, definition), usize::from(offsets.vmtable_import_definition()) ); - assert_eq!( - offset_of!(VMTableImport, from), - usize::from(offsets.vmtable_import_from()) - ); } } /// The fields compiled code needs to access to utilize a WebAssembly linear /// memory imported from another instance. -#[derive(Debug, Clone)] +#[derive(Clone)] #[repr(C)] pub struct VMMemoryImport { /// A pointer to the imported memory description. pub definition: NonNull, - /// A pointer to the `Memory` that owns the memory description. - pub from: Arc, + /// A handle to the `Memory` that owns the memory description. + pub handle: InternalContextHandle, } #[cfg(test)] @@ -254,22 +250,22 @@ mod test_vmmemory_import { usize::from(offsets.vmmemory_import_definition()) ); assert_eq!( - offset_of!(VMMemoryImport, from), - usize::from(offsets.vmmemory_import_from()) + offset_of!(VMMemoryImport, handle), + usize::from(offsets.vmmemory_import_handle()) ); } } /// The fields compiled code needs to access to utilize a WebAssembly global /// variable imported from another instance. -#[derive(Debug, Clone)] +#[derive(Clone)] #[repr(C)] pub struct VMGlobalImport { /// A pointer to the imported global variable description. pub definition: NonNull, - /// A pointer to the `Global` that owns the global description. - pub from: Arc, + /// A handle to the `Global` that owns the global description. + pub handle: InternalContextHandle, } /// # Safety @@ -304,10 +300,6 @@ mod test_vmglobal_import { offset_of!(VMGlobalImport, definition), usize::from(offsets.vmglobal_import_definition()) ); - assert_eq!( - offset_of!(VMGlobalImport, from), - usize::from(offsets.vmglobal_import_from()) - ); } } @@ -466,36 +458,6 @@ mod test_vmtable_definition { } } -/// A typesafe wrapper around the storage for a global variables. -/// -/// # Safety -/// -/// Accessing the different members of this union is always safe because there -/// are no invalid values for any of the types and the whole object is -/// initialized by VMGlobalDefinition::new(). -#[derive(Clone, Copy)] -#[repr(C, align(16))] -pub union VMGlobalDefinitionStorage { - as_i32: i32, - as_u32: u32, - as_f32: f32, - as_i64: i64, - as_u64: u64, - as_f64: f64, - as_u128: u128, - as_funcref: VMFuncRef, - as_externref: VMExternRef, - bytes: [u8; 16], -} - -impl fmt::Debug for VMGlobalDefinitionStorage { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("VMGlobalDefinitionStorage") - .field("bytes", unsafe { &self.bytes }) - .finish() - } -} - /// The storage for a WebAssembly global defined within the instance. /// /// TODO: Pack the globals more densely, rather than using the same size @@ -503,8 +465,8 @@ impl fmt::Debug for VMGlobalDefinitionStorage { #[derive(Debug, Clone)] #[repr(C, align(16))] pub struct VMGlobalDefinition { - storage: VMGlobalDefinitionStorage, - // If more elements are added here, remember to add offset_of tests below! + /// Raw value of the global. + pub val: RawValue, } #[cfg(test)] @@ -547,196 +509,9 @@ impl VMGlobalDefinition { /// Construct a `VMGlobalDefinition`. pub fn new() -> Self { Self { - storage: VMGlobalDefinitionStorage { bytes: [0; 16] }, + val: Default::default(), } } - - /// Return the value as an i32. - /// - /// If this is not an I32 typed global it is unspecified what value is returned. - pub fn to_i32(&self) -> i32 { - unsafe { self.storage.as_i32 } - } - - /// Return a mutable reference to the value as an i32. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has I32 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_i32_mut(&mut self) -> &mut i32 { - &mut self.storage.as_i32 - } - - /// Return a reference to the value as an u32. - /// - /// If this is not an I32 typed global it is unspecified what value is returned. - pub fn to_u32(&self) -> u32 { - unsafe { self.storage.as_u32 } - } - - /// Return a mutable reference to the value as an u32. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has I32 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_u32_mut(&mut self) -> &mut u32 { - &mut self.storage.as_u32 - } - - /// Return a reference to the value as an i64. - /// - /// If this is not an I64 typed global it is unspecified what value is returned. - pub fn to_i64(&self) -> i64 { - unsafe { self.storage.as_i64 } - } - - /// Return a mutable reference to the value as an i64. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has I32 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_i64_mut(&mut self) -> &mut i64 { - &mut self.storage.as_i64 - } - - /// Return a reference to the value as an u64. - /// - /// If this is not an I64 typed global it is unspecified what value is returned. - pub fn to_u64(&self) -> u64 { - unsafe { self.storage.as_u64 } - } - - /// Return a mutable reference to the value as an u64. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has I64 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_u64_mut(&mut self) -> &mut u64 { - &mut self.storage.as_u64 - } - - /// Return a reference to the value as an f32. - /// - /// If this is not an F32 typed global it is unspecified what value is returned. - pub fn to_f32(&self) -> f32 { - unsafe { self.storage.as_f32 } - } - - /// Return a mutable reference to the value as an f32. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has F32 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_f32_mut(&mut self) -> &mut f32 { - &mut self.storage.as_f32 - } - - /// Return a reference to the value as an f64. - /// - /// If this is not an F64 typed global it is unspecified what value is returned. - pub fn to_f64(&self) -> f64 { - unsafe { self.storage.as_f64 } - } - - /// Return a mutable reference to the value as an f64. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has F64 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_f64_mut(&mut self) -> &mut f64 { - &mut self.storage.as_f64 - } - - /// Return a reference to the value as a `VMFuncRef`. - /// - /// If this is not a `VMFuncRef` typed global it is unspecified what value is returned. - pub fn to_funcref(&self) -> VMFuncRef { - unsafe { self.storage.as_funcref } - } - - /// Return a mutable reference to the value as a `VMFuncRef`. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has `VMFuncRef` type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_funcref_mut(&mut self) -> &mut VMFuncRef { - &mut self.storage.as_funcref - } - - /// Return a mutable reference to the value as an `VMExternRef`. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has I32 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_externref_mut(&mut self) -> &mut VMExternRef { - &mut self.storage.as_externref - } - - /// Return a reference to the value as an `VMExternRef`. - /// - /// If this is not an I64 typed global it is unspecified what value is returned. - pub fn to_externref(&self) -> VMExternRef { - unsafe { self.storage.as_externref } - } - - /// Return a reference to the value as an u128. - /// - /// If this is not an V128 typed global it is unspecified what value is returned. - pub fn to_u128(&self) -> u128 { - unsafe { self.storage.as_u128 } - } - - /// Return a mutable reference to the value as an u128. - /// - /// # Safety - /// - /// It is the callers responsibility to make sure the global has V128 type. - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_u128_mut(&mut self) -> &mut u128 { - &mut self.storage.as_u128 - } - - /// Return a reference to the value as bytes. - pub fn to_bytes(&self) -> [u8; 16] { - unsafe { self.storage.bytes } - } - - /// Return a mutable reference to the value as bytes. - /// - /// # Safety - /// - /// Until the returned borrow is dropped, reads and writes of this global - /// must be done exclusively through this borrow. That includes reads and - /// writes of globals inside wasm functions. - pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8; 16] { - &mut self.storage.bytes - } } /// An index into the shared signature registry, usable for checking signatures @@ -795,6 +570,9 @@ pub struct VMCallerCheckedAnyfunc { pub type_index: VMSharedSignatureIndex, /// Function `VMContext` or host env. pub vmctx: VMFunctionEnvironment, + /// Address of the function call trampoline to invoke this function using + /// a dynamic argument list. + pub call_trampoline: VMTrampoline, // If more elements are added here, remember to add offset_of tests below! } @@ -829,18 +607,6 @@ mod test_vmcaller_checked_anyfunc { } } -impl Default for VMCallerCheckedAnyfunc { - fn default() -> Self { - Self { - func_ptr: ptr::null_mut(), - type_index: Default::default(), - vmctx: VMFunctionEnvironment { - vmctx: ptr::null_mut(), - }, - } - } -} - /// An array that stores addresses of builtin functions. We translate code /// to use indirect calls. This way, we don't have to patch the code. #[repr(C)] @@ -942,14 +708,9 @@ impl VMContext { &*((self as *const Self as *mut u8).offset(-Instance::vmctx_offset()) as *const Instance) } - /// Return a reference to the host state associated with this `Instance`. - /// - /// # Safety - /// This is unsafe because it doesn't work on just any `VMContext`, it must - /// be a `VMContext` allocated as part of an `Instance`. #[inline] - pub unsafe fn host_state(&self) -> &dyn Any { - self.instance().host_state() + pub(crate) unsafe fn instance_mut(&mut self) -> &mut Instance { + &mut *((self as *const Self as *mut u8).offset(-Instance::vmctx_offset()) as *mut Instance) } } @@ -957,5 +718,5 @@ impl VMContext { pub type VMTrampoline = unsafe extern "C" fn( *mut VMContext, // callee vmctx *const VMFunctionBody, // function we're actually calling - *mut u128, // space for arguments and return values + *mut RawValue, // space for arguments and return values ); diff --git a/tests/lib/wast/Cargo.toml b/tests/lib/wast/Cargo.toml index e6ac64f43ae..44b8ce3835b 100644 --- a/tests/lib/wast/Cargo.toml +++ b/tests/lib/wast/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] anyhow = "1.0" -wasmer = { path = "../../../lib/api", version = "=2.3.0", default-features = false, features = ["experimental-reference-types-extern-ref"] } +wasmer = { path = "../../../lib/api", version = "=2.3.0", default-features = false } wasmer-wasi = { path = "../../../lib/wasi", version = "=2.3.0" } wasmer-vfs = { path = "../../../lib/vfs", version = "=2.3.0" } wast = "38.0" From 35d06ec3f238f4713344ff189931ec8f9a571581 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 20 May 2022 13:33:37 +0100 Subject: [PATCH 03/24] Ensure that Wasm function call parameters all come from the same context --- lib/api/src/sys/externals/function.rs | 25 ++++++++++++++++++++++++- lib/api/src/sys/native.rs | 6 ++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/api/src/sys/externals/function.rs b/lib/api/src/sys/externals/function.rs index 54fe895252c..9cdbfb2eada 100644 --- a/lib/api/src/sys/externals/function.rs +++ b/lib/api/src/sys/externals/function.rs @@ -269,6 +269,11 @@ impl Function { param_types, &signature, ))); } + if !arg.is_from_context(ctx.as_context_ref()) { + return Err(RuntimeError::new( + "cross-`Context` values are not supported", + )); + } *slot = arg.as_raw(ctx.as_context_mut()); } @@ -618,7 +623,7 @@ mod inner { use crate::sys::context::{ContextInner, ContextMut}; use crate::sys::NativeWasmTypeInto; - use crate::{AsContextMut, ExternRef, Function}; + use crate::{AsContextMut, AsContextRef, ExternRef, Function}; /// A trait to convert a Rust value to a `WasmNativeType` value, /// or to convert `WasmNativeType` value to a Rust value. @@ -653,6 +658,14 @@ mod inner { /// This method panics if `self` cannot fit in the /// `Self::Native` type. fn to_native(self) -> Self::Native; + + /// Returns whether the given value is from the given context. + /// + /// This always returns true for primitive types that can be used with + /// any context. + fn is_from_context(&self, _ctx: impl AsContextRef) -> bool { + true + } } macro_rules! from_to_native_wasm_type { @@ -722,6 +735,11 @@ mod inner { fn from_native(n: Self::Native) -> Self { n } + fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + self.as_ref() + .map(|e| e.is_from_context(ctx)) + .unwrap_or(true) + } } unsafe impl FromToNativeWasmType for Option { @@ -733,6 +751,11 @@ mod inner { fn from_native(n: Self::Native) -> Self { n } + fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + self.as_ref() + .map(|f| f.is_from_context(ctx)) + .unwrap_or(true) + } } #[cfg(test)] diff --git a/lib/api/src/sys/native.rs b/lib/api/src/sys/native.rs index 9024298940e..e28ae7fe256 100644 --- a/lib/api/src/sys/native.rs +++ b/lib/api/src/sys/native.rs @@ -75,6 +75,12 @@ macro_rules! impl_native_traits { .as_ptr() .as_ref() }; + // Ensure all parameters come from the same context. + if $(!FromToNativeWasmType::is_from_context(&$x, ctx.as_context_ref()) ||)* false { + return Err(RuntimeError::new( + "cross-`Context` values are not supported", + )); + } // TODO: when `const fn` related features mature more, we can declare a single array // of the correct size here. let mut params_list = [ $( $x.to_native().into_raw(ctx.as_context_mut()) ),* ]; From 9e53e707671d6996037a355cf6bdd514c3598bcf Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 20 May 2022 14:08:05 +0100 Subject: [PATCH 04/24] Rework the way the Context is passed into function using it --- Cargo.lock | 82 +++++++------- Cargo.toml | 32 ++---- lib/api/src/sys/context.rs | 4 - lib/api/src/sys/exports.rs | 2 +- lib/api/src/sys/extern_ref.rs | 15 +-- lib/api/src/sys/externals/function.rs | 155 ++++++++++++++++---------- lib/api/src/sys/externals/global.rs | 40 ++++--- lib/api/src/sys/externals/memory.rs | 38 +++---- lib/api/src/sys/externals/mod.rs | 6 +- lib/api/src/sys/externals/table.rs | 32 +++--- lib/api/src/sys/instance.rs | 12 +- lib/api/src/sys/mem_access.rs | 4 +- lib/api/src/sys/module.rs | 4 +- lib/api/src/sys/native.rs | 6 +- lib/api/src/sys/native_type.rs | 64 +++++------ lib/api/src/sys/ptr.rs | 10 +- lib/api/src/sys/value.rs | 6 +- lib/types/src/vmoffsets.rs | 20 +++- lib/vm/src/table.rs | 8 +- tests/compilers/wast.rs | 5 +- tests/lib/wast/src/lib.rs | 4 +- tests/lib/wast/src/spectest.rs | 38 ++++--- tests/lib/wast/src/wast.rs | 112 ++++++++----------- 23 files changed, 364 insertions(+), 335 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 919adaecb69..5c459767073 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,9 +60,9 @@ checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" [[package]] name = "arbitrary" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38b6b6b79f671c25e1a3e785b7b82d7562ffc9cd3efdc98627e5668a2472490" +checksum = "25e0a02cf12f1b1f48b14cb7f8217b876d09992b39c816ffb3b1ba64dd979a87" dependencies = [ "derive_arbitrary", ] @@ -560,9 +560,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -581,26 +581,26 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978" dependencies = [ "cfg-if 1.0.0", - "lazy_static", + "once_cell", ] [[package]] @@ -698,9 +698,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98e23c06c035dac87bd802d98f368df73a7f2cb05a66ffbd1f377e821fac4af9" +checksum = "8728db27dd9033a7456655aaeb35fde74425d0f130b4cb18a19171ef38a1b454" dependencies = [ "proc-macro2", "quote", @@ -969,9 +969,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1099,12 +1099,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3" dependencies = [ "autocfg", - "hashbrown 0.11.2", + "hashbrown 0.12.1", "serde", ] @@ -1204,9 +1204,9 @@ checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" dependencies = [ "wasm-bindgen", ] @@ -2570,9 +2570,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" [[package]] name = "unicode-segmentation" @@ -2638,9 +2638,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-test-generator" @@ -2656,9 +2656,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2666,9 +2666,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", "lazy_static", @@ -2681,9 +2681,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2693,9 +2693,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2703,9 +2703,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ "proc-macro2", "quote", @@ -2716,15 +2716,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "wasm-bindgen-test" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4464b3f74729a25f42b1a0cd9e6a515d2f25001f3535a6cfaf35d34a4de3bab" +checksum = "68b30cf2cba841a812f035c40c50f53eb9c56181192a9dd2c71b65e6a87a05ba" dependencies = [ "console_error_panic_hook", "js-sys", @@ -2736,9 +2736,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c5a6f82cc6093a321ca5fb3dc9327fe51675d477b3799b4a9375bac3b7b4c" +checksum = "88ad594bf33e73cafcac2ae9062fc119d4f75f9c77e25022f91c9a64bd5b6463" dependencies = [ "proc-macro2", "quote", @@ -3371,9 +3371,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index d3564e1d60f..9ef617abf14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,10 @@ tempfile = "3.1" # For logging tests using the `RUST_LOG=debug` when testing test-log = { version = "0.2", default-features = false, features = ["trace"] } tracing = { version = "0.1", default-features = false, features = ["log"] } -tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } +tracing-subscriber = { version = "0.3", default-features = false, features = [ + "env-filter", + "fmt", +] } [features] # Don't add the compiler features in default, please add them on the Makefile @@ -98,30 +101,15 @@ compiler = [ "wasmer/compiler", "wasmer-compiler/translator", ] -singlepass = [ - "wasmer-compiler-singlepass", - "compiler", -] -cranelift = [ - "wasmer-compiler-cranelift", - "compiler", -] -llvm = [ - "wasmer-compiler-llvm", - "compiler", -] +singlepass = ["wasmer-compiler-singlepass", "compiler"] +cranelift = ["wasmer-compiler-cranelift", "compiler"] +llvm = ["wasmer-compiler-llvm", "compiler"] middlewares = ["wasmer-middlewares"] # Testing features -test-singlepass = [ - "singlepass", -] -test-cranelift = [ - "cranelift", -] -test-llvm = [ - "llvm", -] +test-singlepass = ["singlepass"] +test-cranelift = ["cranelift"] +test-llvm = ["llvm"] test-universal = [ "test-generator/test-universal", diff --git a/lib/api/src/sys/context.rs b/lib/api/src/sys/context.rs index 46ad4295420..d72e68499db 100644 --- a/lib/api/src/sys/context.rs +++ b/lib/api/src/sys/context.rs @@ -104,10 +104,6 @@ impl ContextMut<'_, T> { &mut self.inner.data } - pub(crate) fn objects(&self) -> &ContextObjects { - &self.inner.objects - } - pub(crate) fn objects_mut(&mut self) -> &mut ContextObjects { &mut self.inner.objects } diff --git a/lib/api/src/sys/exports.rs b/lib/api/src/sys/exports.rs index 194a11104a0..ca04e74b854 100644 --- a/lib/api/src/sys/exports.rs +++ b/lib/api/src/sys/exports.rs @@ -137,7 +137,7 @@ impl Exports { /// Get an export as a `TypedFunction`. pub fn get_native_function( &self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, name: &str, ) -> Result, ExportError> where diff --git a/lib/api/src/sys/extern_ref.rs b/lib/api/src/sys/extern_ref.rs index 395a336dd70..33ff1da3475 100644 --- a/lib/api/src/sys/extern_ref.rs +++ b/lib/api/src/sys/extern_ref.rs @@ -2,8 +2,6 @@ use std::any::Any; use wasmer_vm::{ContextHandle, VMExternObj, VMExternRef}; -use crate::ContextRef; - use super::context::{AsContextMut, AsContextRef}; #[derive(Debug, Clone)] @@ -15,7 +13,7 @@ pub struct ExternRef { impl ExternRef { /// Make a new extern reference - pub fn new(mut ctx: impl AsContextMut, value: T) -> Self + pub fn new(ctx: &mut impl AsContextMut, value: T) -> Self where T: Any + Send + Sync + 'static + Sized, { @@ -25,11 +23,14 @@ impl ExternRef { } /// Try to downcast to the given value. - pub fn downcast<'a, T, U>(&self, ctx: ContextRef<'a, U>) -> Option<&'a T> + pub fn downcast<'a, T>(&self, ctx: &'a impl AsContextRef) -> Option<&'a T> where T: Any + Send + Sync + 'static + Sized, { - self.handle.get(ctx.objects()).as_ref().downcast_ref::() + self.handle + .get(ctx.as_context_ref().objects()) + .as_ref() + .downcast_ref::() } pub(crate) fn vm_externref(&self) -> VMExternRef { @@ -37,7 +38,7 @@ impl ExternRef { } pub(crate) unsafe fn from_vm_externref( - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, vm_externref: VMExternRef, ) -> Self { Self { @@ -55,7 +56,7 @@ impl ExternRef { /// /// Externref and funcref values are tied to a context and can only be used /// with that context. - pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { self.handle.context_id() == ctx.as_context_ref().objects().id() } } diff --git a/lib/api/src/sys/externals/function.rs b/lib/api/src/sys/externals/function.rs index 9cdbfb2eada..cdb0d0ad641 100644 --- a/lib/api/src/sys/externals/function.rs +++ b/lib/api/src/sys/externals/function.rs @@ -74,7 +74,7 @@ impl Function { /// Ok(vec![Value::I32(sum)]) /// }); /// ``` - pub fn new(mut ctx: impl AsContextMut, ty: FT, func: F) -> Self + pub fn new(ctx: &mut impl AsContextMut, ty: FT, func: F) -> Self where FT: Into, F: Fn(ContextMut<'_, T>, &[Value]) -> Result, RuntimeError> @@ -91,11 +91,7 @@ impl Function { let mut ctx = ContextMut::from_raw(raw_ctx as *mut ContextInner); let mut args = Vec::with_capacity(func_ty.params().len()); for (i, ty) in func_ty.params().iter().enumerate() { - args.push(Value::from_raw( - ctx.as_context_mut(), - *ty, - *values_vec.add(i), - )); + args.push(Value::from_raw(&mut ctx, *ty, *values_vec.add(i))); } let returns = func(ctx.as_context_mut(), &args)?; @@ -110,7 +106,7 @@ impl Function { ))); } for (i, ret) in returns.iter().enumerate() { - *values_vec.add(i) = ret.as_raw(ctx.as_context_mut()); + *values_vec.add(i) = ret.as_raw(&ctx); } } Ok(()) @@ -165,7 +161,7 @@ impl Function { /// /// let f = Function::new_native(&store, sum); /// ``` - pub fn new_native(mut ctx: impl AsContextMut, func: F) -> Self + pub fn new_native(ctx: &mut impl AsContextMut, func: F) -> Self where F: HostFunction + 'static + Send + Sync, Args: WasmTypeList, @@ -219,7 +215,7 @@ impl Function { /// assert_eq!(f.ty().params(), vec![Type::I32, Type::I32]); /// assert_eq!(f.ty().results(), vec![Type::I32]); /// ``` - pub fn ty(&self, ctx: impl AsContextRef) -> FunctionType { + pub fn ty(&self, ctx: &impl AsContextRef) -> FunctionType { self.handle .get(ctx.as_context_ref().objects()) .signature @@ -228,7 +224,7 @@ impl Function { fn call_wasm( &self, - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, trampoline: VMTrampoline, params: &[Value], results: &mut [Value], @@ -241,7 +237,7 @@ impl Function { .join(", ") }; // TODO: Avoid cloning the signature here, it's expensive. - let signature = self.ty(ctx.as_context_ref()); + let signature = self.ty(ctx); if signature.params().len() != params.len() { return Err(RuntimeError::new(format!( "Parameters of type [{}] did not match signature {}", @@ -269,12 +265,12 @@ impl Function { param_types, &signature, ))); } - if !arg.is_from_context(ctx.as_context_ref()) { + if !arg.is_from_context(ctx) { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); } - *slot = arg.as_raw(ctx.as_context_mut()); + *slot = arg.as_raw(ctx); } // Call the trampoline. @@ -294,8 +290,7 @@ impl Function { // Load the return values out of `values_vec`. for (index, &value_type) in signature.results().iter().enumerate() { unsafe { - results[index] = - Value::from_raw(ctx.as_context_mut(), value_type, values_vec[index]); + results[index] = Value::from_raw(ctx, value_type, values_vec[index]); } } @@ -318,7 +313,7 @@ impl Function { /// /// assert_eq!(f.param_arity(), 2); /// ``` - pub fn param_arity(&self, ctx: impl AsContextRef) -> usize { + pub fn param_arity(&self, ctx: &impl AsContextRef) -> usize { self.ty(ctx).params().len() } @@ -338,7 +333,7 @@ impl Function { /// /// assert_eq!(f.result_arity(), 1); /// ``` - pub fn result_arity(&self, ctx: impl AsContextRef) -> usize { + pub fn result_arity(&self, ctx: &impl AsContextRef) -> usize { self.ty(ctx).results().len() } @@ -373,7 +368,7 @@ impl Function { /// ``` pub fn call( &self, - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, params: &[Value], ) -> Result, RuntimeError> { let trampoline = unsafe { @@ -384,12 +379,12 @@ impl Function { .as_ref() .call_trampoline }; - let mut results = vec![Value::null(); self.result_arity(ctx.as_context_ref())]; - self.call_wasm(ctx.as_context_mut(), trampoline, params, &mut results)?; + let mut results = vec![Value::null(); self.result_arity(ctx)]; + self.call_wasm(ctx, trampoline, params, &mut results)?; Ok(results.into_boxed_slice()) } - pub(crate) fn vm_funcref(&self, ctx: impl AsContextRef) -> VMFuncRef { + pub(crate) fn vm_funcref(&self, ctx: &impl AsContextRef) -> VMFuncRef { let vm_function = self.handle.get(ctx.as_context_ref().objects()); if vm_function.kind == VMFunctionKind::Dynamic { panic!("dynamic functions cannot be used in tables or as funcrefs"); @@ -397,7 +392,7 @@ impl Function { VMFuncRef(vm_function.anyfunc.as_ptr()) } - pub(crate) unsafe fn from_vm_funcref(mut ctx: impl AsContextMut, funcref: VMFuncRef) -> Self { + pub(crate) unsafe fn from_vm_funcref(ctx: &mut impl AsContextMut, funcref: VMFuncRef) -> Self { let signature = ctx .as_context_mut() .store() @@ -494,7 +489,7 @@ impl Function { /// ``` pub fn native( &self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, ) -> Result, RuntimeError> where Args: WasmTypeList, @@ -534,7 +529,7 @@ impl Function { } pub(crate) fn from_vm_extern( - ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, internal: InternalContextHandle, ) -> Self { Self { @@ -545,7 +540,7 @@ impl Function { } /// Checks whether this `Function` can be used with the given context. - pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { self.handle.context_id() == ctx.as_context_ref().objects().id() } @@ -616,7 +611,7 @@ mod inner { use std::convert::{Infallible, TryInto}; use std::error::Error; use std::panic::{self, AssertUnwindSafe}; - use wasmer_vm::{on_host_stack, VMTrampoline}; + use wasmer_vm::{on_host_stack, VMContext, VMTrampoline}; use wasmer_types::{NativeWasmType, RawValue, Type}; use wasmer_vm::{raise_user_trap, resume_panic, VMFunctionBody}; @@ -663,7 +658,7 @@ mod inner { /// /// This always returns true for primitive types that can be used with /// any context. - fn is_from_context(&self, _ctx: impl AsContextRef) -> bool { + fn is_from_context(&self, _ctx: &impl AsContextRef) -> bool { true } } @@ -735,10 +730,8 @@ mod inner { fn from_native(n: Self::Native) -> Self { n } - fn is_from_context(&self, ctx: impl AsContextRef) -> bool { - self.as_ref() - .map(|e| e.is_from_context(ctx)) - .unwrap_or(true) + fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + self.as_ref().map_or(true, |e| e.is_from_context(ctx)) } } @@ -751,10 +744,8 @@ mod inner { fn from_native(n: Self::Native) -> Self { n } - fn is_from_context(&self, ctx: impl AsContextRef) -> bool { - self.as_ref() - .map(|f| f.is_from_context(ctx)) - .unwrap_or(true) + fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + self.as_ref().map_or(true, |f| f.is_from_context(ctx)) } } @@ -801,7 +792,7 @@ mod inner { /// Constructs `Self` based on an array of values. /// /// # Safety - unsafe fn from_array(ctx: impl AsContextMut, array: Self::Array) -> Self; + unsafe fn from_array(ctx: &mut impl AsContextMut, array: Self::Array) -> Self; /// Constructs `Self` based on a slice of values. /// @@ -812,7 +803,7 @@ mod inner { /// /// # Safety unsafe fn from_slice( - ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, slice: &[RawValue], ) -> Result; @@ -820,7 +811,7 @@ mod inner { /// (list) of values. /// /// # Safety - unsafe fn into_array(self, ctx: impl AsContextMut) -> Self::Array; + unsafe fn into_array(self, ctx: &mut impl AsContextMut) -> Self::Array; /// Allocates and return an empty array of type `Array` that /// will hold a tuple (list) of values, usually to hold the @@ -831,13 +822,18 @@ mod inner { /// `CStruct`. /// /// # Safety - unsafe fn from_c_struct(ctx: impl AsContextMut, c_struct: Self::CStruct) -> Self; + unsafe fn from_c_struct(ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self; /// Builds and returns a C struct of type `CStruct` from a /// tuple (list) of values. /// /// # Safety - unsafe fn into_c_struct(self, ctx: impl AsContextMut) -> Self::CStruct; + unsafe fn into_c_struct(self, ctx: &mut impl AsContextMut) -> Self::CStruct; + + /// Writes the contents of a C struct to an array of `RawValue`. + /// + /// # Safety + unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, ptr: *mut RawValue); /// Get the Wasm types for the tuple (list) of currently /// represented values. @@ -980,7 +976,7 @@ mod inner { #[allow(unused_mut)] #[allow(clippy::unused_unit)] #[allow(clippy::missing_safety_doc)] - unsafe fn from_array(mut _ctx: impl AsContextMut, array: Self::Array) -> Self { + unsafe fn from_array(mut _ctx: &mut impl AsContextMut, array: Self::Array) -> Self { // Unpack items of the array. #[allow(non_snake_case)] let [ $( $x ),* ] = array; @@ -988,19 +984,19 @@ mod inner { // Build the tuple. ( $( - FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_ctx.as_context_mut(), $x)) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_ctx, $x)) ),* ) } #[allow(clippy::missing_safety_doc)] - unsafe fn from_slice(ctx: impl AsContextMut, slice: &[RawValue]) -> Result { + unsafe fn from_slice(ctx: &mut impl AsContextMut, slice: &[RawValue]) -> Result { Ok(Self::from_array(ctx, slice.try_into()?)) } #[allow(unused_mut)] #[allow(clippy::missing_safety_doc)] - unsafe fn into_array(self, mut _ctx: impl AsContextMut) -> Self::Array { + unsafe fn into_array(self, mut _ctx: &mut impl AsContextMut) -> Self::Array { // Unpack items of the tuple. #[allow(non_snake_case)] let ( $( $x ),* ) = self; @@ -1008,7 +1004,7 @@ mod inner { // Build the array. [ $( - FromToNativeWasmType::to_native($x).into_raw(_ctx.as_context_mut()) + FromToNativeWasmType::to_native($x).into_raw(_ctx) ),* ] } @@ -1021,32 +1017,44 @@ mod inner { #[allow(unused_mut)] #[allow(clippy::unused_unit)] #[allow(clippy::missing_safety_doc)] - unsafe fn from_c_struct(mut _ctx: impl AsContextMut, c_struct: Self::CStruct) -> Self { + unsafe fn from_c_struct(mut _ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self { // Unpack items of the C structure. #[allow(non_snake_case)] let $c_struct_name( $( $x ),* ) = c_struct; ( $( - FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_ctx.as_context_mut(), $x)) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_ctx, $x)) ),* ) } #[allow(unused_parens, non_snake_case, unused_mut)] #[allow(clippy::missing_safety_doc)] - unsafe fn into_c_struct(self, mut _ctx: impl AsContextMut) -> Self::CStruct { + unsafe fn into_c_struct(self, mut _ctx: &mut impl AsContextMut) -> Self::CStruct { // Unpack items of the tuple. let ( $( $x ),* ) = self; // Build the C structure. $c_struct_name( $( - FromToNativeWasmType::to_native($x).into_abi(_ctx.as_context_mut()) + FromToNativeWasmType::to_native($x).into_abi(_ctx) ),* ) } + #[allow(non_snake_case)] + unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, _ptr: *mut RawValue) { + // Unpack items of the tuple. + let $c_struct_name( $( $x ),* ) = c_struct; + + let mut _n = 0; + $( + *_ptr.add(_n).cast() = $x; + _n += 1; + )* + } + fn wasm_types() -> &'static [Type] { &[ $( @@ -1073,7 +1081,7 @@ mod inner { /// This is a function that wraps the real host /// function. Its address will be used inside the /// runtime. - unsafe extern "C" fn func_wrapper( env: &StaticFunction, $( $x: $x::Native, )* ) -> Rets::CStruct + unsafe extern "C" fn func_wrapper( env: &StaticFunction, $( $x: <$x::Native as NativeWasmType>::Abi, )* ) -> Rets::CStruct where $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, @@ -1084,12 +1092,15 @@ mod inner { let result = on_host_stack(|| { panic::catch_unwind(AssertUnwindSafe(|| { - (env.func)(ctx.as_context_mut(), $( FromToNativeWasmType::from_native($x) ),* ).into_result() + $( + let $x = FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(&mut ctx, $x)); + )* + (env.func)(ctx.as_context_mut(), $($x),* ).into_result() })) }); match result { - Ok(Ok(result)) => return result.into_c_struct(ctx), + Ok(Ok(result)) => return result.into_c_struct(&mut ctx), Ok(Err(trap)) => raise_user_trap(Box::new(trap)), Err(panic) => resume_panic(panic) , } @@ -1098,9 +1109,35 @@ mod inner { func_wrapper::< T, $( $x, )* Rets, RetsAsResult, Self > as *const VMFunctionBody } + #[allow(non_snake_case)] fn call_trampoline_address() -> VMTrampoline { - todo!() + unsafe extern "C" fn call_trampoline< + $( $x: FromToNativeWasmType, )* + Rets: WasmTypeList, + >( + vmctx: *mut VMContext, + body: *const VMFunctionBody, + args: *mut RawValue, + ) { + let body: unsafe extern "C" fn( + vmctx: *mut VMContext, + $( $x: <$x::Native as NativeWasmType>::Abi, )* + ) -> Rets::CStruct + = std::mem::transmute(body); + + let mut _n = 0; + $( + let $x = *args.add(_n).cast(); + _n += 1; + )* + + let results = body(vmctx, $( $x ),*); + Rets::write_c_struct_to_ptr(results, args); + } + + call_trampoline::<$( $x, )* Rets> } + } }; } @@ -1155,18 +1192,18 @@ mod inner { type CStruct = Self; type Array = [RawValue; 0]; - unsafe fn from_array(_: impl AsContextMut, _: Self::Array) -> Self { + unsafe fn from_array(_: &mut impl AsContextMut, _: Self::Array) -> Self { unreachable!() } unsafe fn from_slice( - _: impl AsContextMut, + _: &mut impl AsContextMut, _: &[RawValue], ) -> Result { unreachable!() } - unsafe fn into_array(self, _: impl AsContextMut) -> Self::Array { + unsafe fn into_array(self, _: &mut impl AsContextMut) -> Self::Array { [] } @@ -1174,14 +1211,16 @@ mod inner { [] } - unsafe fn from_c_struct(_: impl AsContextMut, self_: Self::CStruct) -> Self { + unsafe fn from_c_struct(_: &mut impl AsContextMut, self_: Self::CStruct) -> Self { self_ } - unsafe fn into_c_struct(self, _: impl AsContextMut) -> Self::CStruct { + unsafe fn into_c_struct(self, _: &mut impl AsContextMut) -> Self::CStruct { self } + unsafe fn write_c_struct_to_ptr(_: Self::CStruct, _: *mut RawValue) {} + fn wasm_types() -> &'static [Type] { &[] } diff --git a/lib/api/src/sys/externals/global.rs b/lib/api/src/sys/externals/global.rs index a077847c05e..9e5c6c04cde 100644 --- a/lib/api/src/sys/externals/global.rs +++ b/lib/api/src/sys/externals/global.rs @@ -32,7 +32,7 @@ impl Global { /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Const); /// ``` - pub fn new(ctx: impl AsContextMut, val: Value) -> Self { + pub fn new(ctx: &mut impl AsContextMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Const).unwrap() } @@ -49,17 +49,17 @@ impl Global { /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Var); /// ``` - pub fn new_mut(ctx: impl AsContextMut, val: Value) -> Self { + pub fn new_mut(ctx: &mut impl AsContextMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Var).unwrap() } /// Create a `Global` with the initial value [`Val`] and the provided [`Mutability`]. fn from_value( - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, val: Value, mutability: Mutability, ) -> Result { - if !val.is_from_context(ctx.as_context_mut()) { + if !val.is_from_context(ctx) { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); @@ -69,7 +69,7 @@ impl Global { ty: val.ty(), }); unsafe { - global.vmglobal().as_mut().val = val.as_raw(ctx.as_context_mut()); + global.vmglobal().as_mut().val = val.as_raw(ctx); } Ok(Self { @@ -91,7 +91,7 @@ impl Global { /// assert_eq!(c.ty(), &GlobalType::new(Type::I32, Mutability::Const)); /// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var)); /// ``` - pub fn ty(&self, ctx: impl AsContextRef) -> GlobalType { + pub fn ty(&self, ctx: &impl AsContextRef) -> GlobalType { *self.handle.get(ctx.as_context_ref().objects()).ty() } @@ -107,11 +107,15 @@ impl Global { /// /// assert_eq!(g.get(), Value::I32(1)); /// ``` - pub fn get(&self, mut ctx: impl AsContextMut) -> Value { + pub fn get(&self, ctx: &mut impl AsContextMut) -> Value { unsafe { - let ctx = ctx.as_context_mut(); - let raw = self.handle.get(ctx.objects()).vmglobal().as_ref().val; - let ty = self.handle.get(ctx.objects()).ty().ty; + let raw = self + .handle + .get(ctx.as_context_ref().objects()) + .vmglobal() + .as_ref() + .val; + let ty = self.handle.get(ctx.as_context_ref().objects()).ty().ty; Value::from_raw(ctx, ty, raw) } } @@ -157,19 +161,19 @@ impl Global { /// // This results in an error: `RuntimeError`. /// g.set(Value::I64(2)).unwrap(); /// ``` - pub fn set(&self, mut ctx: impl AsContextMut, val: Value) -> Result<(), RuntimeError> { - if !val.is_from_context(ctx.as_context_mut()) { + pub fn set(&self, ctx: &mut impl AsContextMut, val: Value) -> Result<(), RuntimeError> { + if !val.is_from_context(ctx) { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); } - if self.ty(ctx.as_context_mut()).mutability != Mutability::Var { + if self.ty(ctx).mutability != Mutability::Var { return Err(RuntimeError::new("Attempted to set an immutable global")); } - if val.ty() != self.ty(ctx.as_context_mut()).ty { + if val.ty() != self.ty(ctx).ty { return Err(RuntimeError::new(format!( "Attempted to operate on a global of type {expected} as a global of type {found}", - expected = self.ty(ctx.as_context_mut()).ty, + expected = self.ty(ctx).ty, found = val.ty(), ))); } @@ -178,13 +182,13 @@ impl Global { .get_mut(ctx.as_context_mut().objects_mut()) .vmglobal() .as_mut() - .val = val.as_raw(ctx.as_context_mut()); + .val = val.as_raw(ctx); } Ok(()) } pub(crate) fn from_vm_extern( - ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, internal: InternalContextHandle, ) -> Self { Self { @@ -195,7 +199,7 @@ impl Global { } /// Checks whether this `Global` can be used with the given context. - pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { self.handle.context_id() == ctx.as_context_ref().objects().id() } diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 081dc90011f..136732a773a 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -2,7 +2,7 @@ use crate::sys::context::{AsContextMut, AsContextRef}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; use crate::sys::MemoryType; -use crate::{ContextRef, MemoryAccessError}; +use crate::MemoryAccessError; use std::convert::TryInto; use std::marker::PhantomData; use std::mem; @@ -46,7 +46,7 @@ impl Memory { /// # /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); /// ``` - pub fn new(mut ctx: impl AsContextMut, ty: MemoryType) -> Result { + pub fn new(ctx: &mut impl AsContextMut, ty: MemoryType) -> Result { let mut ctx = ctx.as_context_mut(); let tunables = ctx.store().tunables(); let style = tunables.memory_style(&ty); @@ -70,7 +70,7 @@ impl Memory { /// /// assert_eq!(m.ty(), mt); /// ``` - pub fn ty(&self, ctx: impl AsContextRef) -> MemoryType { + pub fn ty(&self, ctx: &impl AsContextRef) -> MemoryType { self.handle.get(ctx.as_context_ref().objects()).ty() } @@ -79,13 +79,13 @@ impl Memory { // This used by wasmer-emscripten and wasmer-c-api, but should be treated // as deprecated and not used in future code. #[doc(hidden)] - pub fn data_ptr(&self, ctx: impl AsContextRef) -> *mut u8 { - self.buffer(ctx.as_context_ref()).base + pub fn data_ptr(&self, ctx: &impl AsContextRef) -> *mut u8 { + self.buffer(ctx).base } /// Returns the size (in bytes) of the `Memory`. - pub fn data_size(&self, ctx: impl AsContextRef) -> u64 { - self.buffer(ctx.as_context_ref()).len.try_into().unwrap() + pub fn data_size(&self, ctx: &impl AsContextRef) -> u64 { + self.buffer(ctx).len.try_into().unwrap() } /// Returns the size (in [`Pages`]) of the `Memory`. @@ -100,7 +100,7 @@ impl Memory { /// /// assert_eq!(m.size(), Pages(1)); /// ``` - pub fn size(&self, ctx: impl AsContextRef) -> Pages { + pub fn size(&self, ctx: &impl AsContextRef) -> Pages { self.handle.get(ctx.as_context_ref().objects()).size() } @@ -136,7 +136,7 @@ impl Memory { /// ``` pub fn grow( &self, - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, delta: IntoPages, ) -> Result where @@ -156,11 +156,11 @@ impl Memory { /// concurrent writes. pub fn read( &self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, offset: u64, buf: &mut [u8], ) -> Result<(), MemoryAccessError> { - self.buffer(ctx.as_context_ref()).read(offset, buf) + self.buffer(ctx).read(offset, buf) } /// Safely reads bytes from the memory at the given offset. @@ -175,11 +175,11 @@ impl Memory { /// concurrent writes. pub fn read_uninit<'a>( &self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, offset: u64, buf: &'a mut [MaybeUninit], ) -> Result<&'a mut [u8], MemoryAccessError> { - self.buffer(ctx.as_context_ref()).read_uninit(offset, buf) + self.buffer(ctx).read_uninit(offset, buf) } /// Safely writes bytes to the memory at the given offset. @@ -191,15 +191,15 @@ impl Memory { /// concurrent reads/writes. pub fn write( &self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, offset: u64, data: &[u8], ) -> Result<(), MemoryAccessError> { - self.buffer(ctx.as_context_ref()).write(offset, data) + self.buffer(ctx).write(offset, data) } - pub(crate) fn buffer<'a, U>(&'a self, ctx: ContextRef<'a, U>) -> MemoryBuffer<'a> { - let definition = self.handle.get(ctx.objects()).vmmemory(); + pub(crate) fn buffer<'a>(&'a self, ctx: &'a impl AsContextRef) -> MemoryBuffer<'a> { + let definition = self.handle.get(ctx.as_context_ref().objects()).vmmemory(); let def = unsafe { definition.as_ref() }; MemoryBuffer { base: def.base, @@ -209,7 +209,7 @@ impl Memory { } pub(crate) fn from_vm_extern( - ctx: impl AsContextRef, + ctx: &impl AsContextRef, internal: InternalContextHandle, ) -> Self { Self { @@ -220,7 +220,7 @@ impl Memory { } /// Checks whether this `Memory` can be used with the given context. - pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { self.handle.context_id() == ctx.as_context_ref().objects().id() } diff --git a/lib/api/src/sys/externals/mod.rs b/lib/api/src/sys/externals/mod.rs index e0e944d6415..e0e7d91235f 100644 --- a/lib/api/src/sys/externals/mod.rs +++ b/lib/api/src/sys/externals/mod.rs @@ -34,7 +34,7 @@ pub enum Extern { impl Extern { /// Return the underlying type of the inner `Extern`. - pub fn ty(&self, ctx: impl AsContextRef) -> ExternType { + pub fn ty(&self, ctx: &impl AsContextRef) -> ExternType { match self { Self::Function(ft) => ExternType::Function(ft.ty(ctx)), Self::Memory(ft) => ExternType::Memory(ft.ty(ctx)), @@ -44,7 +44,7 @@ impl Extern { } /// Create an `Extern` from an `wasmer_engine::Export`. - pub(crate) fn from_vm_extern(ctx: impl AsContextMut, vm_extern: VMExtern) -> Self { + pub(crate) fn from_vm_extern(ctx: &mut impl AsContextMut, vm_extern: VMExtern) -> Self { match vm_extern { VMExtern::Function(f) => Self::Function(Function::from_vm_extern(ctx, f)), VMExtern::Memory(m) => Self::Memory(Memory::from_vm_extern(ctx, m)), @@ -54,7 +54,7 @@ impl Extern { } /// Checks whether this `Extern` can be used with the given context. - pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { match self { Self::Function(f) => f.is_from_context(ctx), Self::Global(g) => g.is_from_context(ctx), diff --git a/lib/api/src/sys/externals/table.rs b/lib/api/src/sys/externals/table.rs index ed07478696f..d928cfd546b 100644 --- a/lib/api/src/sys/externals/table.rs +++ b/lib/api/src/sys/externals/table.rs @@ -29,10 +29,10 @@ fn set_table_item( } fn value_to_table_element( - ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, val: Value, ) -> Result { - if !val.is_from_context(ctx.as_context_ref()) { + if !val.is_from_context(ctx) { return Err(RuntimeError::new("cannot pass Value across contexts")); } Ok(match val { @@ -46,7 +46,7 @@ fn value_to_table_element( }) } -fn value_from_table_element(ctx: impl AsContextMut, item: wasmer_vm::TableElement) -> Value { +fn value_from_table_element(ctx: &mut impl AsContextMut, item: wasmer_vm::TableElement) -> Value { match item { wasmer_vm::TableElement::FuncRef(funcref) => { Value::FuncRef(funcref.map(|f| unsafe { Function::from_vm_funcref(ctx, f) })) @@ -65,12 +65,12 @@ impl Table { /// This function will construct the `Table` using the store /// [`BaseTunables`][crate::sys::BaseTunables]. pub fn new( - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, ty: TableType, init: Value, ) -> Result { let mut ctx = ctx.as_context_mut(); - let item = value_to_table_element(ctx.as_context_mut(), init)?; + let item = value_to_table_element(&mut ctx, init)?; let tunables = ctx.store().tunables(); let style = tunables.table_style(&ty); let mut table = tunables @@ -83,17 +83,17 @@ impl Table { } Ok(Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), table), + handle: ContextHandle::new(ctx.objects_mut(), table), }) } /// Returns the [`TableType`] of the `Table`. - pub fn ty(&self, ctx: impl AsContextRef) -> TableType { + pub fn ty(&self, ctx: &impl AsContextRef) -> TableType { *self.handle.get(ctx.as_context_ref().objects()).ty() } /// Retrieves an element of the table at the provided `index`. - pub fn get(&self, ctx: impl AsContextMut, index: u32) -> Option { + pub fn get(&self, ctx: &mut impl AsContextMut, index: u32) -> Option { let item = self.handle.get(ctx.as_context_ref().objects()).get(index)?; Some(value_from_table_element(ctx, item)) } @@ -101,11 +101,11 @@ impl Table { /// Sets an element `val` in the Table at the provided `index`. pub fn set( &self, - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, index: u32, val: Value, ) -> Result<(), RuntimeError> { - let item = value_to_table_element(ctx.as_context_mut(), val)?; + let item = value_to_table_element(ctx, val)?; set_table_item( self.handle.get_mut(ctx.as_context_mut().objects_mut()), index, @@ -114,7 +114,7 @@ impl Table { } /// Retrieves the size of the `Table` (in elements) - pub fn size(&self, ctx: impl AsContextRef) -> u32 { + pub fn size(&self, ctx: &impl AsContextRef) -> u32 { self.handle.get(ctx.as_context_ref().objects()).size() } @@ -129,11 +129,11 @@ impl Table { /// Returns an error if the `delta` is out of bounds for the table. pub fn grow( &self, - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, delta: u32, init: Value, ) -> Result { - let item = value_to_table_element(ctx.as_context_mut(), init)?; + let item = value_to_table_element(ctx, init)?; self.handle .get_mut(ctx.as_context_mut().objects_mut()) .grow(delta, item) @@ -148,7 +148,7 @@ impl Table { /// Returns an error if the range is out of bounds of either the source or /// destination tables. pub fn copy( - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, dst_table: &Self, dst_index: u32, src_table: &Self, @@ -176,7 +176,7 @@ impl Table { } pub(crate) fn from_vm_extern( - ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, internal: InternalContextHandle, ) -> Self { Self { @@ -187,7 +187,7 @@ impl Table { } /// Checks whether this `Table` can be used with the given context. - pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { self.handle.context_id() == ctx.as_context_ref().objects().id() } diff --git a/lib/api/src/sys/instance.rs b/lib/api/src/sys/instance.rs index 9cccf7cf2e0..3a5fdb999a9 100644 --- a/lib/api/src/sys/instance.rs +++ b/lib/api/src/sys/instance.rs @@ -108,20 +108,20 @@ impl Instance { /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. pub fn new( - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, module: &Module, imports: &Imports, ) -> Result { let imports = imports .imports_for_module(module) .map_err(InstantiationError::Link)?; - let mut handle = module.instantiate(ctx.as_context_mut(), &imports)?; + let mut handle = module.instantiate(ctx, &imports)?; let exports = module .exports() .map(|export| { let name = export.name().to_string(); let export = handle.lookup(&name).expect("export"); - let extern_ = Extern::from_vm_extern(ctx.as_context_mut(), export); + let extern_ = Extern::from_vm_extern(ctx, export); (name, extern_) }) .collect::(); @@ -146,18 +146,18 @@ impl Instance { /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. pub fn new_by_index( - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, module: &Module, externs: &[Extern], ) -> Result { let imports = externs.to_vec(); - let mut handle = module.instantiate(ctx.as_context_mut(), &imports)?; + let mut handle = module.instantiate(ctx, &imports)?; let exports = module .exports() .map(|export| { let name = export.name().to_string(); let export = handle.lookup(&name).expect("export"); - let extern_ = Extern::from_vm_extern(ctx.as_context_mut(), export); + let extern_ = Extern::from_vm_extern(ctx, export); (name, extern_) }) .collect::(); diff --git a/lib/api/src/sys/mem_access.rs b/lib/api/src/sys/mem_access.rs index db913a71b85..bc92dd140a1 100644 --- a/lib/api/src/sys/mem_access.rs +++ b/lib/api/src/sys/mem_access.rs @@ -64,7 +64,7 @@ impl<'a, T: ValueType> WasmRef<'a, T> { #[inline] pub fn new(ctx: &'a impl AsContextRef, memory: &'a Memory, offset: u64) -> Self { Self { - buffer: memory.buffer(ctx.as_context_ref()), + buffer: memory.buffer(ctx), offset, marker: PhantomData, } @@ -173,7 +173,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { .checked_add(total_len) .ok_or(MemoryAccessError::Overflow)?; Ok(Self { - buffer: memory.buffer(ctx.as_context_ref()), + buffer: memory.buffer(ctx), offset, len, marker: PhantomData, diff --git a/lib/api/src/sys/module.rs b/lib/api/src/sys/module.rs index 241981109bd..3d23b4cbbda 100644 --- a/lib/api/src/sys/module.rs +++ b/lib/api/src/sys/module.rs @@ -278,12 +278,12 @@ impl Module { pub(crate) fn instantiate( &self, - mut ctx: impl AsContextMut, + ctx: &mut impl AsContextMut, imports: &[crate::Extern], ) -> Result { // Ensure all imports come from the same context. for import in imports { - if !import.is_from_context(ctx.as_context_ref()) { + if !import.is_from_context(ctx) { return Err(InstantiationError::BadContext); } } diff --git a/lib/api/src/sys/native.rs b/lib/api/src/sys/native.rs index e28ae7fe256..3866509be8e 100644 --- a/lib/api/src/sys/native.rs +++ b/lib/api/src/sys/native.rs @@ -66,7 +66,7 @@ macro_rules! impl_native_traits { /// Call the typed func and return results. #[allow(unused_mut)] #[allow(clippy::too_many_arguments)] - pub fn call(&self, mut ctx: impl AsContextMut, $( $x: $x, )* ) -> Result { + pub fn call(&self, ctx: &mut impl AsContextMut, $( $x: $x, )* ) -> Result { let anyfunc = unsafe { *self.func .handle @@ -76,14 +76,14 @@ macro_rules! impl_native_traits { .as_ref() }; // Ensure all parameters come from the same context. - if $(!FromToNativeWasmType::is_from_context(&$x, ctx.as_context_ref()) ||)* false { + if $(!FromToNativeWasmType::is_from_context(&$x, ctx) ||)* false { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); } // TODO: when `const fn` related features mature more, we can declare a single array // of the correct size here. - let mut params_list = [ $( $x.to_native().into_raw(ctx.as_context_mut()) ),* ]; + let mut params_list = [ $( $x.to_native().into_raw(ctx) ),* ]; let mut rets_list_array = Rets::empty_array(); let rets_list: &mut [RawValue] = rets_list_array.as_mut(); let using_rets_array; diff --git a/lib/api/src/sys/native_type.rs b/lib/api/src/sys/native_type.rs index edb978a7a0e..4429f9d7e43 100644 --- a/lib/api/src/sys/native_type.rs +++ b/lib/api/src/sys/native_type.rs @@ -12,127 +12,127 @@ use super::context::AsContextMut; /// types with a context. pub trait NativeWasmTypeInto: NativeWasmType + Sized { #[doc(hidden)] - fn into_abi(self, ctx: impl AsContextMut) -> Self::Abi; + fn into_abi(self, ctx: &mut impl AsContextMut) -> Self::Abi; #[doc(hidden)] - unsafe fn from_abi(ctx: impl AsContextMut, abi: Self::Abi) -> Self; + unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self; /// Convert self to raw value representation. - fn into_raw(self, ctx: impl AsContextMut) -> RawValue; + fn into_raw(self, ctx: &mut impl AsContextMut) -> RawValue; /// Convert to self from raw value representation. /// /// # Safety /// - unsafe fn from_raw(ctx: impl AsContextMut, raw: RawValue) -> Self; + unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: RawValue) -> Self; } impl NativeWasmTypeInto for i32 { #[inline] - unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { RawValue { i32: self } } #[inline] - unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { raw.i32 } } impl NativeWasmTypeInto for i64 { #[inline] - unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { RawValue { i64: self } } #[inline] - unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { raw.i64 } } impl NativeWasmTypeInto for f32 { #[inline] - unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { RawValue { f32: self } } #[inline] - unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { raw.f32 } } impl NativeWasmTypeInto for f64 { #[inline] - unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { RawValue { f64: self } } #[inline] - unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { raw.f64 } } impl NativeWasmTypeInto for u128 { #[inline] - unsafe fn from_abi(_ctx: impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { RawValue { u128: self } } #[inline] - unsafe fn from_raw(_ctx: impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { raw.u128 } } @@ -144,23 +144,23 @@ impl NativeWasmType for ExternRef { impl NativeWasmTypeInto for Option { #[inline] - unsafe fn from_abi(ctx: impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { VMExternRef::from_raw(RawValue { externref: abi }) .map(|e| ExternRef::from_vm_externref(ctx, e)) } #[inline] - fn into_abi(self, _ctx: impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { self.map_or(0, |e| unsafe { e.vm_externref().into_raw().externref }) } #[inline] - fn into_raw(self, _ctx: impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { self.map_or(RawValue { externref: 0 }, |e| e.vm_externref().into_raw()) } #[inline] - unsafe fn from_raw(ctx: impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: RawValue) -> Self { VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(ctx, e)) } } @@ -172,22 +172,22 @@ impl NativeWasmType for Function { impl NativeWasmTypeInto for Option { #[inline] - unsafe fn from_abi(ctx: impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { VMFuncRef::from_raw(RawValue { funcref: abi }).map(|f| Function::from_vm_funcref(ctx, f)) } #[inline] - fn into_abi(self, ctx: impl AsContextMut) -> Self::Abi { + fn into_abi(self, ctx: &mut impl AsContextMut) -> Self::Abi { self.map_or(0, |f| unsafe { f.vm_funcref(ctx).into_raw().externref }) } #[inline] - fn into_raw(self, ctx: impl AsContextMut) -> RawValue { + fn into_raw(self, ctx: &mut impl AsContextMut) -> RawValue { self.map_or(RawValue { externref: 0 }, |e| e.vm_funcref(ctx).into_raw()) } #[inline] - unsafe fn from_raw(ctx: impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: RawValue) -> Self { VMFuncRef::from_raw(raw).map(|f| Function::from_vm_funcref(ctx, f)) } } diff --git a/lib/api/src/sys/ptr.rs b/lib/api/src/sys/ptr.rs index 158cfc44a25..46a09983c28 100644 --- a/lib/api/src/sys/ptr.rs +++ b/lib/api/src/sys/ptr.rs @@ -148,7 +148,7 @@ impl WasmPtr { /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, ctx: impl AsContextRef, memory: &Memory) -> Result { + pub fn read(self, ctx: &impl AsContextRef, memory: &Memory) -> Result { self.deref(&ctx, memory).read() } @@ -156,7 +156,7 @@ impl WasmPtr { #[inline] pub fn write( self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, memory: &Memory, val: T, ) -> Result<(), MemoryAccessError> { @@ -185,7 +185,7 @@ impl WasmPtr { #[inline] pub fn read_until( self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, memory: &Memory, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { @@ -210,7 +210,7 @@ impl WasmPtr { #[inline] pub fn read_utf8_string( self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, memory: &Memory, len: M::Offset, ) -> Result { @@ -225,7 +225,7 @@ impl WasmPtr { #[inline] pub fn read_utf8_string_with_nul( self, - ctx: impl AsContextRef, + ctx: &impl AsContextRef, memory: &Memory, ) -> Result { let vec = self.read_until(ctx, memory, |&byte| byte == 0)?; diff --git a/lib/api/src/sys/value.rs b/lib/api/src/sys/value.rs index 49974035c37..9e23a966e0d 100644 --- a/lib/api/src/sys/value.rs +++ b/lib/api/src/sys/value.rs @@ -92,7 +92,7 @@ impl Value { } /// Converts the `Value` into a `RawValue`. - pub fn as_raw(&self, ctx: impl AsContextRef) -> RawValue { + pub fn as_raw(&self, ctx: &impl AsContextRef) -> RawValue { match *self { Self::I32(i32) => RawValue { i32 }, Self::I64(i64) => RawValue { i64 }, @@ -111,7 +111,7 @@ impl Value { /// /// # Safety /// - pub unsafe fn from_raw(ctx: impl AsContextMut, ty: Type, raw: RawValue) -> Self { + pub unsafe fn from_raw(ctx: &mut impl AsContextMut, ty: Type, raw: RawValue) -> Self { match ty { Type::I32 => Self::I32(raw.i32), Type::I64 => Self::I64(raw.i64), @@ -134,7 +134,7 @@ impl Value { /// /// Externref and funcref values are tied to a context and can only be used /// with that context. - pub fn is_from_context(&self, ctx: impl AsContextRef) -> bool { + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { match self { Self::I32(_) | Self::I64(_) diff --git a/lib/types/src/vmoffsets.rs b/lib/types/src/vmoffsets.rs index 8c3f43c2ae5..81cd0b0422c 100644 --- a/lib/types/src/vmoffsets.rs +++ b/lib/types/src/vmoffsets.rs @@ -117,7 +117,7 @@ impl VMBuiltinFunctionIndex { } /// Returns the total number of builtin functions. pub const fn builtin_functions_total_number() -> u32 { - 26 + 24 } /// Return the index as an u32 number. @@ -213,9 +213,14 @@ impl VMOffsets { 1 * self.pointer_size } + /// The offset of the `handle` field. + pub const fn vmfunction_import_handle(&self) -> u8 { + 2 * self.pointer_size + } + /// Return the size of `VMFunctionImport`. pub const fn size_of_vmfunction_import(&self) -> u8 { - 2 * self.pointer_size + 3 * self.pointer_size } } @@ -264,7 +269,7 @@ impl VMOffsets { /// Return the size of `VMTableImport`. pub const fn size_of_vmtable_import(&self) -> u8 { - 3 * self.pointer_size + 2 * self.pointer_size } } @@ -309,7 +314,7 @@ impl VMOffsets { /// Return the size of `VMMemoryImport`. pub const fn size_of_vmmemory_import(&self) -> u8 { - 3 * self.pointer_size + 2 * self.pointer_size } } @@ -397,9 +402,14 @@ impl VMOffsets { 2 * self.pointer_size } + /// The offset of the `call_trampoline` field. + pub const fn vmcaller_checked_anyfunc_call_trampoline(&self) -> u8 { + 3 * self.pointer_size + } + /// Return the size of `VMCallerCheckedAnyfunc`. pub const fn size_of_vmcaller_checked_anyfunc(&self) -> u8 { - 3 * self.pointer_size + 4 * self.pointer_size } } diff --git a/lib/vm/src/table.rs b/lib/vm/src/table.rs index 1a8965c32ee..364a81f11ff 100644 --- a/lib/vm/src/table.rs +++ b/lib/vm/src/table.rs @@ -228,10 +228,10 @@ impl VMTable { match self.vec.get_mut(index as usize) { Some(slot) => { match (self.table.ty, reference) { - ( - ValType::ExternRef, - r @ TableElement::ExternRef(_) | r @ TableElement::FuncRef(_), - ) => { + (ValType::ExternRef, r @ TableElement::ExternRef(_)) => { + *slot = r.into(); + } + (ValType::FuncRef, r @ TableElement::FuncRef(_)) => { *slot = r.into(); } // This path should never be hit by the generated code due to Wasm diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 576e62e19fa..0910c279867 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -1,4 +1,4 @@ -use ::wasmer::Features; +use ::wasmer::{Context, Features}; use std::path::Path; use wasmer_wast::Wast; @@ -35,7 +35,8 @@ pub fn run_wast(mut config: crate::Config, wast_path: &str) -> anyhow::Result<() config.set_nan_canonicalization(try_nan_canonicalization); let store = config.store(); - let mut wast = Wast::new_with_spectest(store); + let context = Context::new(&store, ()); + let mut wast = Wast::new_with_spectest(context); // `bulk-memory-operations/bulk.wast` checks for a message that // specifies which element is uninitialized, but our traps don't // shepherd that information out. diff --git a/tests/lib/wast/src/lib.rs b/tests/lib/wast/src/lib.rs index 4cca798b795..0e709053ddd 100644 --- a/tests/lib/wast/src/lib.rs +++ b/tests/lib/wast/src/lib.rs @@ -19,12 +19,12 @@ mod error; mod spectest; -mod wasi_wast; +//mod wasi_wast; mod wast; pub use crate::error::{DirectiveError, DirectiveErrors}; pub use crate::spectest::spectest_importobject; -pub use crate::wasi_wast::{WasiFileSystemKind, WasiTest}; +//pub use crate::wasi_wast::{WasiFileSystemKind, WasiTest}; pub use crate::wast::Wast; /// Version number of this crate. diff --git a/tests/lib/wast/src/spectest.rs b/tests/lib/wast/src/spectest.rs index 0cd42d00156..36d0d848a36 100644 --- a/tests/lib/wast/src/spectest.rs +++ b/tests/lib/wast/src/spectest.rs @@ -2,31 +2,39 @@ use wasmer::*; /// Return an instance implementing the "spectest" interface used in the /// spec testsuite. -pub fn spectest_importobject(store: &Store) -> Imports { - let print = Function::new_native(store, || {}); - let print_i32 = Function::new_native(store, |val: i32| println!("{}: i32", val)); - let print_i64 = Function::new_native(store, |val: i64| println!("{}: i64", val)); - let print_f32 = Function::new_native(store, |val: f32| println!("{}: f32", val)); - let print_f64 = Function::new_native(store, |val: f64| println!("{}: f64", val)); - let print_i32_f32 = Function::new_native(store, |i: i32, f: f32| { +pub fn spectest_importobject(context: &mut Context<()>) -> Imports { + let print = Function::new_native(context, |_: ContextMut<'_, ()>| {}); + let print_i32 = Function::new_native(context, |_: ContextMut<'_, ()>, val: i32| { + println!("{}: i32", val) + }); + let print_i64 = Function::new_native(context, |_: ContextMut<'_, ()>, val: i64| { + println!("{}: i64", val) + }); + let print_f32 = Function::new_native(context, |_: ContextMut<'_, ()>, val: f32| { + println!("{}: f32", val) + }); + let print_f64 = Function::new_native(context, |_: ContextMut<'_, ()>, val: f64| { + println!("{}: f64", val) + }); + let print_i32_f32 = Function::new_native(context, |_: ContextMut<'_, ()>, i: i32, f: f32| { println!("{}: i32", i); println!("{}: f32", f); }); - let print_f64_f64 = Function::new_native(store, |f1: f64, f2: f64| { + let print_f64_f64 = Function::new_native(context, |_: ContextMut<'_, ()>, f1: f64, f2: f64| { println!("{}: f64", f1); println!("{}: f64", f2); }); - let global_i32 = Global::new(store, Val::I32(666)); - let global_i64 = Global::new(store, Val::I64(666)); - let global_f32 = Global::new(store, Val::F32(f32::from_bits(0x4426_8000))); - let global_f64 = Global::new(store, Val::F64(f64::from_bits(0x4084_d000_0000_0000))); + let global_i32 = Global::new(context, Value::I32(666)); + let global_i64 = Global::new(context, Value::I64(666)); + let global_f32 = Global::new(context, Value::F32(f32::from_bits(0x4426_8000))); + let global_f64 = Global::new(context, Value::F64(f64::from_bits(0x4084_d000_0000_0000))); - let ty = TableType::new(ValType::FuncRef, 10, Some(20)); - let table = Table::new(store, ty, Val::FuncRef(None)).unwrap(); + let ty = TableType::new(Type::FuncRef, 10, Some(20)); + let table = Table::new(context, ty, Value::FuncRef(None)).unwrap(); let ty = MemoryType::new(1, Some(2), false); - let memory = Memory::new(store, ty).unwrap(); + let memory = Memory::new(context, ty).unwrap(); imports! { "spectest" => { diff --git a/tests/lib/wast/src/wast.rs b/tests/lib/wast/src/wast.rs index 9b21b8bd3fe..3eb689b40b8 100644 --- a/tests/lib/wast/src/wast.rs +++ b/tests/lib/wast/src/wast.rs @@ -1,7 +1,7 @@ use crate::error::{DirectiveError, DirectiveErrors}; use crate::spectest::spectest_importobject; use anyhow::{anyhow, bail, Result}; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::collections::{HashMap, HashSet}; use std::path::Path; use std::str; use wasmer::*; @@ -23,11 +23,8 @@ pub struct Wast { match_trap_messages: HashMap, /// If the current module was an allowed failure, we allow test to fail current_is_allowed_failure: bool, - /// Extern-ref manager: used for testing extern refs: they're referred to by - /// number in WAST, so we map here. - extern_refs: BTreeMap, - /// The wasm Store - store: Store, + /// The context in which the tests are executing. + context: Context<()>, /// A flag indicating if Wast tests should stop as soon as one test fails. pub fail_fast: bool, /// A flag indicating that assert_trap and assert_exhaustion should be skipped. @@ -37,16 +34,15 @@ pub struct Wast { impl Wast { /// Construct a new instance of `Wast` with a given imports. - pub fn new(store: Store, import_object: Imports) -> Self { + pub fn new(context: Context<()>, import_object: Imports) -> Self { Self { current: None, - store, + context, import_object, allowed_instantiation_failures: HashSet::new(), match_trap_messages: HashMap::new(), current_is_allowed_failure: false, instances: HashMap::new(), - extern_refs: BTreeMap::new(), fail_fast: true, disable_assert_trap_exhaustion: false, } @@ -72,9 +68,9 @@ impl Wast { } /// Construct a new instance of `Wast` with the spectests imports. - pub fn new_with_spectest(store: Store) -> Self { - let import_object = spectest_importobject(&store); - Self::new(store, import_object) + pub fn new_with_spectest(mut context: Context<()>) -> Self { + let import_object = spectest_importobject(&mut context); + Self::new(context, import_object) } fn get_instance(&self, instance_name: Option<&str>) -> Result { @@ -92,7 +88,7 @@ impl Wast { } /// Perform the action portion of a command. - fn perform_execute(&mut self, exec: wast::WastExecute<'_>) -> Result> { + fn perform_execute(&mut self, exec: wast::WastExecute<'_>) -> Result> { match exec { wast::WastExecute::Invoke(invoke) => self.perform_invoke(invoke), wast::WastExecute::Module(mut module) => { @@ -104,7 +100,7 @@ impl Wast { } } - fn perform_invoke(&mut self, exec: wast::WastInvoke<'_>) -> Result> { + fn perform_invoke(&mut self, exec: wast::WastInvoke<'_>) -> Result> { let values = exec .args .iter() @@ -115,7 +111,7 @@ impl Wast { fn assert_return( &self, - result: Result>, + result: Result>, results: &[wast::AssertExpression], ) -> Result<()> { let values = result?; @@ -123,7 +119,7 @@ impl Wast { if self.val_matches(v, e)? { continue; } - if let Val::V128(bits) = v { + if let Value::V128(bits) = v { if let wast::AssertExpression::V128(pattern) = e { bail!( "expected {:?}, got {:?} (v128 bits: {})", @@ -138,7 +134,7 @@ impl Wast { Ok(()) } - fn assert_trap(&self, result: Result>, expected: &str) -> Result<()> { + fn assert_trap(&self, result: Result>, expected: &str) -> Result<()> { let actual = match result { Ok(values) => bail!("expected trap, got {:?}", values), Err(t) => format!("{}", t), @@ -369,8 +365,8 @@ impl Wast { Ok(()) } - fn instantiate(&self, module: &[u8]) -> Result { - let module = Module::new(&self.store, module)?; + fn instantiate(&mut self, module: &[u8]) -> Result { + let module = Module::new(self.context.store(), module)?; let mut imports = self.import_object.clone(); for import in module.imports() { @@ -385,7 +381,7 @@ impl Wast { imports.register_namespace(module_name, instance.exports.clone()); } - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&mut self.context, &module, &imports)?; Ok(instance) } @@ -401,45 +397,39 @@ impl Wast { &mut self, instance_name: Option<&str>, field: &str, - args: &[Val], - ) -> Result> { + args: &[Value], + ) -> Result> { let instance = self.get_instance(instance_name)?; let func: &Function = instance.exports.get(field)?; - match func.call(args) { + match func.call(&mut self.context, args) { Ok(result) => Ok(result.into()), Err(e) => Err(e.into()), } } /// Get the value of an exported global from an instance. - fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result> { + fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result> { let instance = self.get_instance(instance_name)?; let global: &Global = instance.exports.get(field)?; - Ok(vec![global.get()]) + Ok(vec![global.get(&mut self.context)]) } - /// Translate from a `script::Value` to a `Val`. - fn runtime_value(&mut self, v: &wast::Expression<'_>) -> Result { + /// Translate from a `script::Value` to a `Value`. + fn runtime_value(&mut self, v: &wast::Expression<'_>) -> Result { use wast::Instruction::*; if v.instrs.len() != 1 { bail!("too many instructions in {:?}", v); } Ok(match &v.instrs[0] { - I32Const(x) => Val::I32(*x), - I64Const(x) => Val::I64(*x), - F32Const(x) => Val::F32(f32::from_bits(x.bits)), - F64Const(x) => Val::F64(f64::from_bits(x.bits)), - V128Const(x) => Val::V128(u128::from_le_bytes(x.to_le_bytes())), - RefNull(wast::HeapType::Func) => Val::FuncRef(None), - RefNull(wast::HeapType::Extern) => Val::null(), - RefExtern(number) => { - let extern_ref = self - .extern_refs - .entry(*number) - .or_insert_with(|| ExternRef::new(*number)); - Val::ExternRef(extern_ref.clone()) - } + I32Const(x) => Value::I32(*x), + I64Const(x) => Value::I64(*x), + F32Const(x) => Value::F32(f32::from_bits(x.bits)), + F64Const(x) => Value::F64(f64::from_bits(x.bits)), + V128Const(x) => Value::V128(u128::from_le_bytes(x.to_le_bytes())), + RefNull(wast::HeapType::Func) => Value::FuncRef(None), + RefNull(wast::HeapType::Extern) => Value::null(), + RefExtern(number) => Value::ExternRef(Some(ExternRef::new(&mut self.context, *number))), other => bail!("couldn't convert {:?} to a runtime value", other), }) } @@ -476,38 +466,30 @@ impl Wast { .map_or(false, |alternative| actual.contains(alternative)) } - fn val_matches(&self, actual: &Val, expected: &wast::AssertExpression) -> Result { + fn val_matches(&self, actual: &Value, expected: &wast::AssertExpression) -> Result { Ok(match (actual, expected) { - (Val::I32(a), wast::AssertExpression::I32(b)) => a == b, - (Val::I64(a), wast::AssertExpression::I64(b)) => a == b, + (Value::I32(a), wast::AssertExpression::I32(b)) => a == b, + (Value::I64(a), wast::AssertExpression::I64(b)) => a == b, // Note that these float comparisons are comparing bits, not float // values, so we're testing for bit-for-bit equivalence - (Val::F32(a), wast::AssertExpression::F32(b)) => f32_matches(*a, b), - (Val::F64(a), wast::AssertExpression::F64(b)) => f64_matches(*a, b), - (Val::V128(a), wast::AssertExpression::V128(b)) => v128_matches(*a, b), - (Val::FuncRef(None), wast::AssertExpression::RefNull(Some(wast::HeapType::Func))) => { + (Value::F32(a), wast::AssertExpression::F32(b)) => f32_matches(*a, b), + (Value::F64(a), wast::AssertExpression::F64(b)) => f64_matches(*a, b), + (Value::V128(a), wast::AssertExpression::V128(b)) => v128_matches(*a, b), + (Value::FuncRef(None), wast::AssertExpression::RefNull(Some(wast::HeapType::Func))) => { true } - (Val::FuncRef(Some(_)), wast::AssertExpression::RefNull(_)) => false, - (Val::FuncRef(None), wast::AssertExpression::RefFunc(None)) => true, - (Val::FuncRef(None), wast::AssertExpression::RefFunc(Some(_))) => false, + (Value::FuncRef(Some(_)), wast::AssertExpression::RefNull(_)) => false, + (Value::FuncRef(None), wast::AssertExpression::RefFunc(None)) => true, + (Value::FuncRef(None), wast::AssertExpression::RefFunc(Some(_))) => false, ( - Val::ExternRef(extern_ref), + Value::ExternRef(None), wast::AssertExpression::RefNull(Some(wast::HeapType::Extern)), - ) if extern_ref.is_null() => true, - (Val::ExternRef(extern_ref), wast::AssertExpression::RefExtern(_)) - if extern_ref.is_null() => - { - false - } + ) => true, + (Value::ExternRef(None), wast::AssertExpression::RefExtern(_)) => false, - (Val::ExternRef(_), wast::AssertExpression::RefNull(_)) => false, - (Val::ExternRef(extern_ref), wast::AssertExpression::RefExtern(num)) => { - if let Some(stored_extern_ref) = self.extern_refs.get(num) { - extern_ref == stored_extern_ref - } else { - false - } + (Value::ExternRef(Some(_)), wast::AssertExpression::RefNull(_)) => false, + (Value::ExternRef(Some(extern_ref)), wast::AssertExpression::RefExtern(num)) => { + extern_ref.downcast(&self.context) == Some(num) } _ => bail!( "don't know how to compare {:?} and {:?} yet", From 1c578fa8939e9cbbffae49e3492c47c663b9c769 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 20 May 2022 15:34:13 +0100 Subject: [PATCH 05/24] Update hello_world.rs example --- examples/hello_world.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/hello_world.rs b/examples/hello_world.rs index dba2fff8be5..6451460a4c2 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -6,7 +6,9 @@ //! cargo run --example hello-world --release --features "cranelift" //! ``` -use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, TypedFunction}; +use wasmer::{ + imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TypedFunction, +}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -50,11 +52,13 @@ fn main() -> anyhow::Result<()> { // A `Module` is a compiled WebAssembly module that isn't ready to execute yet. let module = Module::new(&store, wasm_bytes)?; - // Next we'll set up our `Module` so that we can execute it. + // Next we'll set up our `Module` so that we can execute it. First, create + // a `Context` in which to instantiate our `Module`. + let mut context = Context::new(&store, ()); // We define a function to act as our "env" "say_hello" function imported in the // Wasm program above. - fn say_hello_world() { + fn say_hello_world(ctx: ContextMut<'_, ()>) { println!("Hello, world!") } @@ -63,7 +67,7 @@ fn main() -> anyhow::Result<()> { // We use the default namespace "env". "env" => { // And call our function "say_hello". - "say_hello" => Function::new_native(&store, say_hello_world), + "say_hello" => Function::new_native(&mut context, say_hello_world), } }; @@ -71,17 +75,18 @@ fn main() -> anyhow::Result<()> { // // An `Instance` is a compiled WebAssembly module that has been set up // and is ready to execute. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut context, &module, &import_object)?; // We get the `TypedFunction` with no parameters and no results from the instance. // // Recall that the Wasm module exported a function named "run", this is getting // that exported function from the `Instance`. - let run_func: TypedFunction<(), ()> = instance.exports.get_native_function("run")?; + let run_func: TypedFunction<(), ()> = + instance.exports.get_native_function(&mut context, "run")?; // Finally, we call our exported Wasm function which will call our "say_hello" // function and return. - run_func.call()?; + run_func.call(&mut context)?; Ok(()) } From d3d363bab2f56b0bee220390426198c50dc0ed72 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Wed, 25 May 2022 16:44:35 +0200 Subject: [PATCH 06/24] Migrated WASI and WAST to Wasmer 3.0 API Co-authored-by: Manos Pitsidianakis --- lib/c-api/src/wasm_c_api/unstable/wasi.rs | 4 +- lib/c-api/src/wasm_c_api/wasi/mod.rs | 4 +- lib/wasi/src/lib.rs | 752 +++++++++---------- lib/wasi/src/macros.rs | 8 +- lib/wasi/src/state/pipe.rs | 9 +- lib/wasi/src/state/socket.rs | 49 +- lib/wasi/src/syscalls/legacy/snapshot0.rs | 70 +- lib/wasi/src/syscalls/mod.rs | 851 +++++++++++++--------- lib/wasi/src/syscalls/wasi.rs | 189 ++--- lib/wasi/src/syscalls/wasix32.rs | 447 ++++++------ lib/wasi/src/syscalls/wasix64.rs | 447 ++++++------ tests/lib/wast/src/lib.rs | 4 +- tests/lib/wast/src/wasi_wast.rs | 22 +- 13 files changed, 1557 insertions(+), 1299 deletions(-) diff --git a/lib/c-api/src/wasm_c_api/unstable/wasi.rs b/lib/c-api/src/wasm_c_api/unstable/wasi.rs index b3832669f55..793db9ce079 100644 --- a/lib/c-api/src/wasm_c_api/unstable/wasi.rs +++ b/lib/c-api/src/wasm_c_api/unstable/wasi.rs @@ -6,7 +6,7 @@ use super::super::{ wasi::wasi_env_t, }; use wasmer_api::{Exportable, Extern}; -use wasmer_wasi::{generate_import_object_from_env, get_wasi_version}; +use wasmer_wasi::{generate_import_object_from_ctx, get_wasi_version}; /// Unstable non-standard type wrapping `wasm_extern_t` with the /// addition of two `wasm_name_t` respectively for the module name and @@ -170,7 +170,7 @@ fn wasi_get_unordered_imports_inner( let version = c_try!(get_wasi_version(&module.inner, false) .ok_or("could not detect a WASI version on the given module")); - let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version); + let import_object = generate_import_object_from_ctx(store, wasi_env.inner.clone(), version); imports.set_buffer( import_object diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 3daacd8e70e..3aa36fb48d0 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -16,7 +16,7 @@ use std::os::raw::c_char; use std::slice; use wasmer_api::{Exportable, Extern}; use wasmer_wasi::{ - generate_import_object_from_env, get_wasi_version, Pipe, WasiEnv, WasiFile, WasiState, + generate_import_object_from_ctx, get_wasi_version, Pipe, WasiEnv, WasiFile, WasiState, WasiStateBuilder, WasiVersion, }; @@ -343,7 +343,7 @@ fn wasi_get_imports_inner( let version = c_try!(get_wasi_version(&module.inner, false) .ok_or("could not detect a WASI version on the given module")); - let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version); + let import_object = generate_import_object_from_ctx(store, wasi_env.inner.clone(), version); imports.set_buffer(c_try!(module .inner diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index 8d60b8e7526..2940817142c 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -50,6 +50,7 @@ pub use crate::syscalls::types; pub use crate::utils::{ get_wasi_version, get_wasi_versions, is_wasi_module, is_wasix_module, WasiVersion, }; +use wasmer::{Context, ContextMut}; pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus}; #[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")] pub use wasmer_vfs::FsError as WasiFsError; @@ -63,8 +64,8 @@ use derivative::*; use std::ops::Deref; use thiserror::Error; use wasmer::{ - imports, Function, Imports, LazyInit, Memory, Memory32, MemoryAccessError, MemorySize, Module, - Store, TypedFunction, WasmerEnv, + imports, namespace, AsContextMut, Exports, Function, Imports, Memory, Memory32, + MemoryAccessError, MemorySize, Module, TypedFunction, }; pub use runtime::{ @@ -143,30 +144,25 @@ impl WasiThread { } /// The environment provided to the WASI imports. -#[derive(Derivative, Clone, WasmerEnv)] +#[derive(Derivative, Clone)] #[derivative(Debug)] +#[allow(dead_code)] pub struct WasiEnv { /// ID of this thread (zero is the main thread) id: WasiThreadId, /// Represents a reference to the memory - #[wasmer(export)] - memory: LazyInit, + memory: Option, /// If the module has it then map the thread start #[derivative(Debug = "ignore")] - #[wasmer(export(optional = true, name = "_thread_start"))] - thread_start: LazyInit>, + thread_start: Option>, #[derivative(Debug = "ignore")] - #[wasmer(export(optional = true, name = "_reactor_work"))] - reactor_work: LazyInit>, + reactor_work: Option>, #[derivative(Debug = "ignore")] - #[wasmer(export(optional = true, name = "_reactor_finish"))] - reactor_finish: LazyInit>, + reactor_finish: Option>, #[derivative(Debug = "ignore")] - #[wasmer(export(optional = true, name = "_malloc"))] - malloc: LazyInit>, + malloc: Option>, #[derivative(Debug = "ignore")] - #[wasmer(export(optional = true, name = "_free"))] - free: LazyInit>, + free: Option>, /// Shared state of the WASI system. Manages all the data that the /// executing WASI program can see. pub state: Arc, @@ -175,16 +171,17 @@ pub struct WasiEnv { } impl WasiEnv { + /// Create a new WasiEnv from a WasiState (memory will be set to None) pub fn new(state: WasiState) -> Self { Self { id: 0u32.into(), state: Arc::new(state), - memory: LazyInit::new(), - thread_start: LazyInit::new(), - reactor_work: LazyInit::new(), - reactor_finish: LazyInit::new(), - malloc: LazyInit::new(), - free: LazyInit::new(), + memory: None, + thread_start: None, + reactor_work: None, + reactor_finish: None, + malloc: None, + free: None, runtime: Arc::new(PluggableRuntimeImplementation::default()), } } @@ -226,34 +223,18 @@ impl WasiEnv { thread } - /// Get the WASI state - /// - /// Be careful when using this in host functions that call into Wasm: - /// if the lock is held and the Wasm calls into a host function that tries - /// to lock this mutex, the program will deadlock. - pub fn state(&self) -> &WasiState { - self.state.deref() - } - - /// Get a reference to the memory - pub fn memory(&self) -> &Memory { - self.memory - .get_ref() - .expect("Memory should be set on `WasiEnv` first") - } - /// Copy the lazy reference so that when it's initialized during the /// export phase, all the other references get a copy of it - pub fn memory_clone(&self) -> LazyInit { + pub fn memory_clone(&self) -> Option { self.memory.clone() } /// Get an `Imports` for a specific version of WASI detected in the module. pub fn import_object(&mut self, module: &Module) -> Result { let wasi_version = get_wasi_version(module, false).ok_or(WasiError::UnknownWasiVersion)?; - Ok(generate_import_object_from_env( - module.store(), - self.clone(), + let mut context = Context::new(module.store(), self.clone()); + Ok(generate_import_object_from_ctx( + &mut context.as_context_mut(), wasi_version, )) } @@ -268,9 +249,10 @@ impl WasiEnv { get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; let mut resolver = Imports::new(); + let mut context = Context::new(module.store(), self.clone()); for version in wasi_versions.iter() { let new_import_object = - generate_import_object_from_env(module.store(), self.clone(), *version); + generate_import_object_from_ctx(&mut context.as_context_mut(), *version); for ((n, m), e) in new_import_object.into_iter() { resolver.define(&n, &m, e); } @@ -335,7 +317,25 @@ impl WasiEnv { (memory, state) } - pub(crate) fn get_memory_and_wasi_state_and_inodes( + /// Set the memory of the WasiEnv (can only be done once) + pub fn set_memory(&mut self, memory: Memory) { + if self.memory.is_some() { + panic!("Memory of a WasiEnv can only be set once!"); + } + self.memory = Some(memory); + } + + /// Get memory, that needs to have been set fist + pub fn memory(&self) -> &Memory { + self.memory.as_ref().unwrap() + } + + /// Get the WASI state + pub fn state(&self) -> &WasiState { + &self.state + } + + pub fn get_memory_and_wasi_state_and_inodes( &self, _mem_index: u32, ) -> (&Memory, &WasiState, RwLockReadGuard) { @@ -356,359 +356,371 @@ impl WasiEnv { } } -/// Create an [`Imports`] with an existing [`WasiEnv`]. `WasiEnv` -/// needs a [`WasiState`], that can be constructed from a -/// [`WasiStateBuilder`](state::WasiStateBuilder). -pub fn generate_import_object_from_env( - store: &Store, - env: WasiEnv, +/// Create an [`Imports`] from a [`Context`] +pub fn generate_import_object_from_ctx( + ctx: &mut ContextMut<'_, WasiEnv>, version: WasiVersion, ) -> Imports { match version { - WasiVersion::Snapshot0 => generate_import_object_snapshot0(store, env), - WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env), - WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, env), - WasiVersion::Snapshot1 | WasiVersion::Latest => { - generate_import_object_snapshot1(store, env) - } + WasiVersion::Snapshot0 => generate_import_object_snapshot0(ctx), + WasiVersion::Snapshot1 | WasiVersion::Latest => generate_import_object_snapshot1(ctx), + WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(ctx), + WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(ctx), + } +} + +fn wasi_unstable_exports(ctx: &mut ContextMut<'_, WasiEnv>) -> Exports { + let namespace = namespace! { + "args_get" => Function::new_native(ctx, args_get::), + "args_sizes_get" => Function::new_native(ctx, args_sizes_get::), + "clock_res_get" => Function::new_native(ctx, clock_res_get::), + "clock_time_get" => Function::new_native(ctx, clock_time_get::), + "environ_get" => Function::new_native(ctx, environ_get::), + "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get::), + "fd_advise" => Function::new_native(ctx, fd_advise), + "fd_allocate" => Function::new_native(ctx, fd_allocate), + "fd_close" => Function::new_native(ctx, fd_close), + "fd_datasync" => Function::new_native(ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(ctx, legacy::snapshot0::fd_filestat_get), + "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(ctx, fd_pread::), + "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_native(ctx, fd_pwrite::), + "fd_read" => Function::new_native(ctx, fd_read::), + "fd_readdir" => Function::new_native(ctx, fd_readdir::), + "fd_renumber" => Function::new_native(ctx, fd_renumber), + "fd_seek" => Function::new_native(ctx, legacy::snapshot0::fd_seek), + "fd_sync" => Function::new_native(ctx, fd_sync), + "fd_tell" => Function::new_native(ctx, fd_tell::), + "fd_write" => Function::new_native(ctx, fd_write::), + "path_create_directory" => Function::new_native(ctx, path_create_directory::), + "path_filestat_get" => Function::new_native(ctx, legacy::snapshot0::path_filestat_get), + "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times::), + "path_link" => Function::new_native(ctx, path_link::), + "path_open" => Function::new_native(ctx, path_open::), + "path_readlink" => Function::new_native(ctx, path_readlink::), + "path_remove_directory" => Function::new_native(ctx, path_remove_directory::), + "path_rename" => Function::new_native(ctx, path_rename::), + "path_symlink" => Function::new_native(ctx, path_symlink::), + "path_unlink_file" => Function::new_native(ctx, path_unlink_file::), + "poll_oneoff" => Function::new_native(ctx, legacy::snapshot0::poll_oneoff), + "proc_exit" => Function::new_native(ctx, proc_exit), + "proc_raise" => Function::new_native(ctx, proc_raise), + "random_get" => Function::new_native(ctx, random_get::), + "sched_yield" => Function::new_native(ctx, sched_yield), + "sock_recv" => Function::new_native(ctx, sock_recv::), + "sock_send" => Function::new_native(ctx, sock_send::), + "sock_shutdown" => Function::new_native(ctx, sock_shutdown), + }; + namespace +} + +fn wasi_snapshot_preview1_exports(ctx: &mut ContextMut<'_, WasiEnv>) -> Exports { + let namespace = namespace! { + "args_get" => Function::new_native(ctx, args_get::), + "args_sizes_get" => Function::new_native(ctx, args_sizes_get::), + "clock_res_get" => Function::new_native(ctx, clock_res_get::), + "clock_time_get" => Function::new_native(ctx, clock_time_get::), + "environ_get" => Function::new_native(ctx, environ_get::), + "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get::), + "fd_advise" => Function::new_native(ctx, fd_advise), + "fd_allocate" => Function::new_native(ctx, fd_allocate), + "fd_close" => Function::new_native(ctx, fd_close), + "fd_datasync" => Function::new_native(ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(ctx, fd_filestat_get::), + "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(ctx, fd_pread::), + "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_native(ctx, fd_pwrite::), + "fd_read" => Function::new_native(ctx, fd_read::), + "fd_readdir" => Function::new_native(ctx, fd_readdir::), + "fd_renumber" => Function::new_native(ctx, fd_renumber), + "fd_seek" => Function::new_native(ctx, fd_seek::), + "fd_sync" => Function::new_native(ctx, fd_sync), + "fd_tell" => Function::new_native(ctx, fd_tell::), + "fd_write" => Function::new_native(ctx, fd_write::), + "path_create_directory" => Function::new_native(ctx, path_create_directory::), + "path_filestat_get" => Function::new_native(ctx, path_filestat_get::), + "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times::), + "path_link" => Function::new_native(ctx, path_link::), + "path_open" => Function::new_native(ctx, path_open::), + "path_readlink" => Function::new_native(ctx, path_readlink::), + "path_remove_directory" => Function::new_native(ctx, path_remove_directory::), + "path_rename" => Function::new_native(ctx, path_rename::), + "path_symlink" => Function::new_native(ctx, path_symlink::), + "path_unlink_file" => Function::new_native(ctx, path_unlink_file::), + "poll_oneoff" => Function::new_native(ctx, poll_oneoff::), + "proc_exit" => Function::new_native(ctx, proc_exit), + "proc_raise" => Function::new_native(ctx, proc_raise), + "random_get" => Function::new_native(ctx, random_get::), + "sched_yield" => Function::new_native(ctx, sched_yield), + "sock_recv" => Function::new_native(ctx, sock_recv::), + "sock_send" => Function::new_native(ctx, sock_send::), + "sock_shutdown" => Function::new_native(ctx, sock_shutdown), + }; + namespace +} +pub fn import_object_for_all_wasi_versions(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { + let wasi_unstable_exports = wasi_unstable_exports(ctx); + let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(ctx); + imports! { + "wasi_unstable" => wasi_unstable_exports, + "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports, } } /// Combines a state generating function with the import list for legacy WASI -fn generate_import_object_snapshot0(store: &Store, env: WasiEnv) -> Imports { - use self::wasi::*; +fn generate_import_object_snapshot0(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { + let wasi_unstable_exports = wasi_unstable_exports(ctx); imports! { - "wasi_unstable" => { - "args_get" => Function::new_native_with_env(store, env.clone(), args_get), - "args_sizes_get" => Function::new_native_with_env(store, env.clone(), args_sizes_get), - "clock_res_get" => Function::new_native_with_env(store, env.clone(), clock_res_get), - "clock_time_get" => Function::new_native_with_env(store, env.clone(), clock_time_get), - "environ_get" => Function::new_native_with_env(store, env.clone(), environ_get), - "environ_sizes_get" => Function::new_native_with_env(store, env.clone(), environ_sizes_get), - "fd_advise" => Function::new_native_with_env(store, env.clone(), fd_advise), - "fd_allocate" => Function::new_native_with_env(store, env.clone(), fd_allocate), - "fd_close" => Function::new_native_with_env(store, env.clone(), fd_close), - "fd_datasync" => Function::new_native_with_env(store, env.clone(), fd_datasync), - "fd_fdstat_get" => Function::new_native_with_env(store, env.clone(), fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native_with_env(store, env.clone(), legacy::snapshot0::fd_filestat_get), - "fd_filestat_set_size" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_times), - "fd_pread" => Function::new_native_with_env(store, env.clone(), fd_pread), - "fd_prestat_get" => Function::new_native_with_env(store, env.clone(), fd_prestat_get), - "fd_prestat_dir_name" => Function::new_native_with_env(store, env.clone(), fd_prestat_dir_name), - "fd_pwrite" => Function::new_native_with_env(store, env.clone(), fd_pwrite), - "fd_read" => Function::new_native_with_env(store, env.clone(), fd_read), - "fd_readdir" => Function::new_native_with_env(store, env.clone(), fd_readdir), - "fd_renumber" => Function::new_native_with_env(store, env.clone(), fd_renumber), - "fd_seek" => Function::new_native_with_env(store, env.clone(), legacy::snapshot0::fd_seek), - "fd_sync" => Function::new_native_with_env(store, env.clone(), fd_sync), - "fd_tell" => Function::new_native_with_env(store, env.clone(), fd_tell), - "fd_write" => Function::new_native_with_env(store, env.clone(), fd_write), - "path_create_directory" => Function::new_native_with_env(store, env.clone(), path_create_directory), - "path_filestat_get" => Function::new_native_with_env(store, env.clone(), legacy::snapshot0::path_filestat_get), - "path_filestat_set_times" => Function::new_native_with_env(store, env.clone(), path_filestat_set_times), - "path_link" => Function::new_native_with_env(store, env.clone(), path_link), - "path_open" => Function::new_native_with_env(store, env.clone(), path_open), - "path_readlink" => Function::new_native_with_env(store, env.clone(), path_readlink), - "path_remove_directory" => Function::new_native_with_env(store, env.clone(), path_remove_directory), - "path_rename" => Function::new_native_with_env(store, env.clone(), path_rename), - "path_symlink" => Function::new_native_with_env(store, env.clone(), path_symlink), - "path_unlink_file" => Function::new_native_with_env(store, env.clone(), path_unlink_file), - "poll_oneoff" => Function::new_native_with_env(store, env.clone(), legacy::snapshot0::poll_oneoff), - "proc_exit" => Function::new_native_with_env(store, env.clone(), proc_exit), - "proc_raise" => Function::new_native_with_env(store, env.clone(), proc_raise), - "random_get" => Function::new_native_with_env(store, env.clone(), random_get), - "sched_yield" => Function::new_native_with_env(store, env.clone(), sched_yield), - "sock_recv" => Function::new_native_with_env(store, env.clone(), sock_recv), - "sock_send" => Function::new_native_with_env(store, env.clone(), sock_send), - "sock_shutdown" => Function::new_native_with_env(store, env, sock_shutdown), - }, + "wasi_unstable" => wasi_unstable_exports } } -/// Combines a state generating function with the import list for snapshot 1 -fn generate_import_object_snapshot1(store: &Store, env: WasiEnv) -> Imports { - use self::wasi::*; +fn generate_import_object_snapshot1(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { + let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(ctx); imports! { - "wasi_snapshot_preview1" => { - "args_get" => Function::new_native_with_env(store, env.clone(), args_get), - "args_sizes_get" => Function::new_native_with_env(store, env.clone(), args_sizes_get), - "clock_res_get" => Function::new_native_with_env(store, env.clone(), clock_res_get), - "clock_time_get" => Function::new_native_with_env(store, env.clone(), clock_time_get), - "environ_get" => Function::new_native_with_env(store, env.clone(), environ_get), - "environ_sizes_get" => Function::new_native_with_env(store, env.clone(), environ_sizes_get), - "fd_advise" => Function::new_native_with_env(store, env.clone(), fd_advise), - "fd_allocate" => Function::new_native_with_env(store, env.clone(), fd_allocate), - "fd_close" => Function::new_native_with_env(store, env.clone(), fd_close), - "fd_datasync" => Function::new_native_with_env(store, env.clone(), fd_datasync), - "fd_fdstat_get" => Function::new_native_with_env(store, env.clone(), fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native_with_env(store, env.clone(), fd_filestat_get), - "fd_filestat_set_size" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_times), - "fd_pread" => Function::new_native_with_env(store, env.clone(), fd_pread), - "fd_prestat_get" => Function::new_native_with_env(store, env.clone(), fd_prestat_get), - "fd_prestat_dir_name" => Function::new_native_with_env(store, env.clone(), fd_prestat_dir_name), - "fd_pwrite" => Function::new_native_with_env(store, env.clone(), fd_pwrite), - "fd_read" => Function::new_native_with_env(store, env.clone(), fd_read), - "fd_readdir" => Function::new_native_with_env(store, env.clone(), fd_readdir), - "fd_renumber" => Function::new_native_with_env(store, env.clone(), fd_renumber), - "fd_seek" => Function::new_native_with_env(store, env.clone(), fd_seek), - "fd_sync" => Function::new_native_with_env(store, env.clone(), fd_sync), - "fd_tell" => Function::new_native_with_env(store, env.clone(), fd_tell), - "fd_write" => Function::new_native_with_env(store, env.clone(), fd_write), - "path_create_directory" => Function::new_native_with_env(store, env.clone(), path_create_directory), - "path_filestat_get" => Function::new_native_with_env(store, env.clone(), path_filestat_get), - "path_filestat_set_times" => Function::new_native_with_env(store, env.clone(), path_filestat_set_times), - "path_link" => Function::new_native_with_env(store, env.clone(), path_link), - "path_open" => Function::new_native_with_env(store, env.clone(), path_open), - "path_readlink" => Function::new_native_with_env(store, env.clone(), path_readlink), - "path_remove_directory" => Function::new_native_with_env(store, env.clone(), path_remove_directory), - "path_rename" => Function::new_native_with_env(store, env.clone(), path_rename), - "path_symlink" => Function::new_native_with_env(store, env.clone(), path_symlink), - "path_unlink_file" => Function::new_native_with_env(store, env.clone(), path_unlink_file), - "poll_oneoff" => Function::new_native_with_env(store, env.clone(), poll_oneoff), - "proc_exit" => Function::new_native_with_env(store, env.clone(), proc_exit), - "proc_raise" => Function::new_native_with_env(store, env.clone(), proc_raise), - "random_get" => Function::new_native_with_env(store, env.clone(), random_get), - "sched_yield" => Function::new_native_with_env(store, env.clone(), sched_yield), - "sock_recv" => Function::new_native_with_env(store, env.clone(), sock_recv), - "sock_send" => Function::new_native_with_env(store, env.clone(), sock_send), - "sock_shutdown" => Function::new_native_with_env(store, env, sock_shutdown), - } + "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports } } /// Combines a state generating function with the import list for snapshot 1 -fn generate_import_object_wasix32_v1(store: &Store, env: WasiEnv) -> Imports { +fn generate_import_object_wasix32_v1(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { use self::wasix32::*; imports! { "wasix_32v1" => { - "args_get" => Function::new_native_with_env(store, env.clone(), args_get), - "args_sizes_get" => Function::new_native_with_env(store, env.clone(), args_sizes_get), - "clock_res_get" => Function::new_native_with_env(store, env.clone(), clock_res_get), - "clock_time_get" => Function::new_native_with_env(store, env.clone(), clock_time_get), - "environ_get" => Function::new_native_with_env(store, env.clone(), environ_get), - "environ_sizes_get" => Function::new_native_with_env(store, env.clone(), environ_sizes_get), - "fd_advise" => Function::new_native_with_env(store, env.clone(), fd_advise), - "fd_allocate" => Function::new_native_with_env(store, env.clone(), fd_allocate), - "fd_close" => Function::new_native_with_env(store, env.clone(), fd_close), - "fd_datasync" => Function::new_native_with_env(store, env.clone(), fd_datasync), - "fd_fdstat_get" => Function::new_native_with_env(store, env.clone(), fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native_with_env(store, env.clone(), fd_filestat_get), - "fd_filestat_set_size" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_times), - "fd_pread" => Function::new_native_with_env(store, env.clone(), fd_pread), - "fd_prestat_get" => Function::new_native_with_env(store, env.clone(), fd_prestat_get), - "fd_prestat_dir_name" => Function::new_native_with_env(store, env.clone(), fd_prestat_dir_name), - "fd_pwrite" => Function::new_native_with_env(store, env.clone(), fd_pwrite), - "fd_read" => Function::new_native_with_env(store, env.clone(), fd_read), - "fd_readdir" => Function::new_native_with_env(store, env.clone(), fd_readdir), - "fd_renumber" => Function::new_native_with_env(store, env.clone(), fd_renumber), - "fd_dup" => Function::new_native_with_env(store, env.clone(), fd_dup), - "fd_event" => Function::new_native_with_env(store, env.clone(), fd_event), - "fd_seek" => Function::new_native_with_env(store, env.clone(), fd_seek), - "fd_sync" => Function::new_native_with_env(store, env.clone(), fd_sync), - "fd_tell" => Function::new_native_with_env(store, env.clone(), fd_tell), - "fd_write" => Function::new_native_with_env(store, env.clone(), fd_write), - "fd_pipe" => Function::new_native_with_env(store, env.clone(), fd_pipe), - "path_create_directory" => Function::new_native_with_env(store, env.clone(), path_create_directory), - "path_filestat_get" => Function::new_native_with_env(store, env.clone(), path_filestat_get), - "path_filestat_set_times" => Function::new_native_with_env(store, env.clone(), path_filestat_set_times), - "path_link" => Function::new_native_with_env(store, env.clone(), path_link), - "path_open" => Function::new_native_with_env(store, env.clone(), path_open), - "path_readlink" => Function::new_native_with_env(store, env.clone(), path_readlink), - "path_remove_directory" => Function::new_native_with_env(store, env.clone(), path_remove_directory), - "path_rename" => Function::new_native_with_env(store, env.clone(), path_rename), - "path_symlink" => Function::new_native_with_env(store, env.clone(), path_symlink), - "path_unlink_file" => Function::new_native_with_env(store, env.clone(), path_unlink_file), - "poll_oneoff" => Function::new_native_with_env(store, env.clone(), poll_oneoff), - "proc_exit" => Function::new_native_with_env(store, env.clone(), proc_exit), - "proc_raise" => Function::new_native_with_env(store, env.clone(), proc_raise), - "random_get" => Function::new_native_with_env(store, env.clone(), random_get), - "tty_get" => Function::new_native_with_env(store, env.clone(), tty_get), - "tty_set" => Function::new_native_with_env(store, env.clone(), tty_set), - "getcwd" => Function::new_native_with_env(store, env.clone(), getcwd), - "chdir" => Function::new_native_with_env(store, env.clone(), chdir), - "thread_spawn" => Function::new_native_with_env(store, env.clone(), thread_spawn), - "thread_sleep" => Function::new_native_with_env(store, env.clone(), thread_sleep), - "thread_id" => Function::new_native_with_env(store, env.clone(), thread_id), - "thread_join" => Function::new_native_with_env(store, env.clone(), thread_join), - "thread_parallelism" => Function::new_native_with_env(store, env.clone(), thread_parallelism), - "thread_exit" => Function::new_native_with_env(store, env.clone(), thread_exit), - "sched_yield" => Function::new_native_with_env(store, env.clone(), sched_yield), - "getpid" => Function::new_native_with_env(store, env.clone(), getpid), - "process_spawn" => Function::new_native_with_env(store, env.clone(), process_spawn), - "bus_open_local" => Function::new_native_with_env(store, env.clone(), bus_open_local), - "bus_open_remote" => Function::new_native_with_env(store, env.clone(), bus_open_remote), - "bus_close" => Function::new_native_with_env(store, env.clone(), bus_close), - "bus_call" => Function::new_native_with_env(store, env.clone(), bus_call), - "bus_subcall" => Function::new_native_with_env(store, env.clone(), bus_subcall), - "bus_poll" => Function::new_native_with_env(store, env.clone(), bus_poll), - "call_reply" => Function::new_native_with_env(store, env.clone(), call_reply), - "call_fault" => Function::new_native_with_env(store, env.clone(), call_fault), - "call_close" => Function::new_native_with_env(store, env.clone(), call_close), - "ws_connect" => Function::new_native_with_env(store, env.clone(), ws_connect), - "http_request" => Function::new_native_with_env(store, env.clone(), http_request), - "http_status" => Function::new_native_with_env(store, env.clone(), http_status), - "port_bridge" => Function::new_native_with_env(store, env.clone(), port_bridge), - "port_unbridge" => Function::new_native_with_env(store, env.clone(), port_unbridge), - "port_dhcp_acquire" => Function::new_native_with_env(store, env.clone(), port_dhcp_acquire), - "port_addr_add" => Function::new_native_with_env(store, env.clone(), port_addr_add), - "port_addr_remove" => Function::new_native_with_env(store, env.clone(), port_addr_remove), - "port_addr_clear" => Function::new_native_with_env(store, env.clone(), port_addr_clear), - "port_addr_list" => Function::new_native_with_env(store, env.clone(), port_addr_list), - "port_mac" => Function::new_native_with_env(store, env.clone(), port_mac), - "port_gateway_set" => Function::new_native_with_env(store, env.clone(), port_gateway_set), - "port_route_add" => Function::new_native_with_env(store, env.clone(), port_route_add), - "port_route_remove" => Function::new_native_with_env(store, env.clone(), port_route_remove), - "port_route_clear" => Function::new_native_with_env(store, env.clone(), port_route_clear), - "port_route_list" => Function::new_native_with_env(store, env.clone(), port_route_list), - "sock_status" => Function::new_native_with_env(store, env.clone(), sock_status), - "sock_addr_local" => Function::new_native_with_env(store, env.clone(), sock_addr_local), - "sock_addr_peer" => Function::new_native_with_env(store, env.clone(), sock_addr_peer), - "sock_open" => Function::new_native_with_env(store, env.clone(), sock_open), - "sock_set_opt_flag" => Function::new_native_with_env(store, env.clone(), sock_set_opt_flag), - "sock_get_opt_flag" => Function::new_native_with_env(store, env.clone(), sock_get_opt_flag), - "sock_set_opt_time" => Function::new_native_with_env(store, env.clone(), sock_set_opt_time), - "sock_get_opt_time" => Function::new_native_with_env(store, env.clone(), sock_get_opt_time), - "sock_set_opt_size" => Function::new_native_with_env(store, env.clone(), sock_set_opt_size), - "sock_get_opt_size" => Function::new_native_with_env(store, env.clone(), sock_get_opt_size), - "sock_join_multicast_v4" => Function::new_native_with_env(store, env.clone(), sock_join_multicast_v4), - "sock_leave_multicast_v4" => Function::new_native_with_env(store, env.clone(), sock_leave_multicast_v4), - "sock_join_multicast_v6" => Function::new_native_with_env(store, env.clone(), sock_join_multicast_v6), - "sock_leave_multicast_v6" => Function::new_native_with_env(store, env.clone(), sock_leave_multicast_v6), - "sock_bind" => Function::new_native_with_env(store, env.clone(), sock_bind), - "sock_listen" => Function::new_native_with_env(store, env.clone(), sock_listen), - "sock_accept" => Function::new_native_with_env(store, env.clone(), sock_accept), - "sock_connect" => Function::new_native_with_env(store, env.clone(), sock_connect), - "sock_recv" => Function::new_native_with_env(store, env.clone(), sock_recv), - "sock_recv_from" => Function::new_native_with_env(store, env.clone(), sock_recv_from), - "sock_send" => Function::new_native_with_env(store, env.clone(), sock_send), - "sock_send_to" => Function::new_native_with_env(store, env.clone(), sock_send_to), - "sock_send_file" => Function::new_native_with_env(store, env.clone(), sock_send_file), - "sock_shutdown" => Function::new_native_with_env(store, env.clone(), sock_shutdown), - "resolve" => Function::new_native_with_env(store, env, resolve), + "args_get" => Function::new_native(ctx, args_get), + "args_sizes_get" => Function::new_native(ctx, args_sizes_get), + "clock_res_get" => Function::new_native(ctx, clock_res_get), + "clock_time_get" => Function::new_native(ctx, clock_time_get), + "environ_get" => Function::new_native(ctx, environ_get), + "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get), + "fd_advise" => Function::new_native(ctx, fd_advise), + "fd_allocate" => Function::new_native(ctx, fd_allocate), + "fd_close" => Function::new_native(ctx, fd_close), + "fd_datasync" => Function::new_native(ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get), + "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(ctx, fd_filestat_get), + "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(ctx, fd_pread), + "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get), + "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name), + "fd_pwrite" => Function::new_native(ctx, fd_pwrite), + "fd_read" => Function::new_native(ctx, fd_read), + "fd_readdir" => Function::new_native(ctx, fd_readdir), + "fd_renumber" => Function::new_native(ctx, fd_renumber), + "fd_dup" => Function::new_native(ctx, fd_dup), + "fd_event" => Function::new_native(ctx, fd_event), + "fd_seek" => Function::new_native(ctx, fd_seek), + "fd_sync" => Function::new_native(ctx, fd_sync), + "fd_tell" => Function::new_native(ctx, fd_tell), + "fd_write" => Function::new_native(ctx, fd_write), + "fd_pipe" => Function::new_native(ctx, fd_pipe), + "path_create_directory" => Function::new_native(ctx, path_create_directory), + "path_filestat_get" => Function::new_native(ctx, path_filestat_get), + "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times), + "path_link" => Function::new_native(ctx, path_link), + "path_open" => Function::new_native(ctx, path_open), + "path_readlink" => Function::new_native(ctx, path_readlink), + "path_remove_directory" => Function::new_native(ctx, path_remove_directory), + "path_rename" => Function::new_native(ctx, path_rename), + "path_symlink" => Function::new_native(ctx, path_symlink), + "path_unlink_file" => Function::new_native(ctx, path_unlink_file), + "poll_oneoff" => Function::new_native(ctx, poll_oneoff), + "proc_exit" => Function::new_native(ctx, proc_exit), + "proc_raise" => Function::new_native(ctx, proc_raise), + "random_get" => Function::new_native(ctx, random_get), + "tty_get" => Function::new_native(ctx, tty_get), + "tty_set" => Function::new_native(ctx, tty_set), + "getcwd" => Function::new_native(ctx, getcwd), + "chdir" => Function::new_native(ctx, chdir), + "thread_spawn" => Function::new_native(ctx, thread_spawn), + "thread_sleep" => Function::new_native(ctx, thread_sleep), + "thread_id" => Function::new_native(ctx, thread_id), + "thread_join" => Function::new_native(ctx, thread_join), + "thread_parallelism" => Function::new_native(ctx, thread_parallelism), + "thread_exit" => Function::new_native(ctx, thread_exit), + "sched_yield" => Function::new_native(ctx, sched_yield), + "getpid" => Function::new_native(ctx, getpid), + "process_spawn" => Function::new_native(ctx, process_spawn), + "bus_open_local" => Function::new_native(ctx, bus_open_local), + "bus_open_remote" => Function::new_native(ctx, bus_open_remote), + "bus_close" => Function::new_native(ctx, bus_close), + "bus_call" => Function::new_native(ctx, bus_call), + "bus_subcall" => Function::new_native(ctx, bus_subcall), + "bus_poll" => Function::new_native(ctx, bus_poll), + "call_reply" => Function::new_native(ctx, call_reply), + "call_fault" => Function::new_native(ctx, call_fault), + "call_close" => Function::new_native(ctx, call_close), + "ws_connect" => Function::new_native(ctx, ws_connect), + "http_request" => Function::new_native(ctx, http_request), + "http_status" => Function::new_native(ctx, http_status), + "port_bridge" => Function::new_native(ctx, port_bridge), + "port_unbridge" => Function::new_native(ctx, port_unbridge), + "port_dhcp_acquire" => Function::new_native(ctx, port_dhcp_acquire), + "port_addr_add" => Function::new_native(ctx, port_addr_add), + "port_addr_remove" => Function::new_native(ctx, port_addr_remove), + "port_addr_clear" => Function::new_native(ctx, port_addr_clear), + "port_addr_list" => Function::new_native(ctx, port_addr_list), + "port_mac" => Function::new_native(ctx, port_mac), + "port_gateway_set" => Function::new_native(ctx, port_gateway_set), + "port_route_add" => Function::new_native(ctx, port_route_add), + "port_route_remove" => Function::new_native(ctx, port_route_remove), + "port_route_clear" => Function::new_native(ctx, port_route_clear), + "port_route_list" => Function::new_native(ctx, port_route_list), + "sock_status" => Function::new_native(ctx, sock_status), + "sock_addr_local" => Function::new_native(ctx, sock_addr_local), + "sock_addr_peer" => Function::new_native(ctx, sock_addr_peer), + "sock_open" => Function::new_native(ctx, sock_open), + "sock_set_opt_flag" => Function::new_native(ctx, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_native(ctx, sock_get_opt_flag), + "sock_set_opt_time" => Function::new_native(ctx, sock_set_opt_time), + "sock_get_opt_time" => Function::new_native(ctx, sock_get_opt_time), + "sock_set_opt_size" => Function::new_native(ctx, sock_set_opt_size), + "sock_get_opt_size" => Function::new_native(ctx, sock_get_opt_size), + "sock_join_multicast_v4" => Function::new_native(ctx, sock_join_multicast_v4), + "sock_leave_multicast_v4" => Function::new_native(ctx, sock_leave_multicast_v4), + "sock_join_multicast_v6" => Function::new_native(ctx, sock_join_multicast_v6), + "sock_leave_multicast_v6" => Function::new_native(ctx, sock_leave_multicast_v6), + "sock_bind" => Function::new_native(ctx, sock_bind), + "sock_listen" => Function::new_native(ctx, sock_listen), + "sock_accept" => Function::new_native(ctx, sock_accept), + "sock_connect" => Function::new_native(ctx, sock_connect), + "sock_recv" => Function::new_native(ctx, sock_recv), + "sock_recv_from" => Function::new_native(ctx, sock_recv_from), + "sock_send" => Function::new_native(ctx, sock_send), + "sock_send_to" => Function::new_native(ctx, sock_send_to), + "sock_send_file" => Function::new_native(ctx, sock_send_file), + "sock_shutdown" => Function::new_native(ctx, sock_shutdown), + "resolve" => Function::new_native(ctx, resolve), } } } -fn generate_import_object_wasix64_v1(store: &Store, env: WasiEnv) -> Imports { +fn generate_import_object_wasix64_v1(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { use self::wasix64::*; imports! { "wasix_64v1" => { - "args_get" => Function::new_native_with_env(store, env.clone(), args_get), - "args_sizes_get" => Function::new_native_with_env(store, env.clone(), args_sizes_get), - "clock_res_get" => Function::new_native_with_env(store, env.clone(), clock_res_get), - "clock_time_get" => Function::new_native_with_env(store, env.clone(), clock_time_get), - "environ_get" => Function::new_native_with_env(store, env.clone(), environ_get), - "environ_sizes_get" => Function::new_native_with_env(store, env.clone(), environ_sizes_get), - "fd_advise" => Function::new_native_with_env(store, env.clone(), fd_advise), - "fd_allocate" => Function::new_native_with_env(store, env.clone(), fd_allocate), - "fd_close" => Function::new_native_with_env(store, env.clone(), fd_close), - "fd_datasync" => Function::new_native_with_env(store, env.clone(), fd_datasync), - "fd_fdstat_get" => Function::new_native_with_env(store, env.clone(), fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native_with_env(store, env.clone(), fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native_with_env(store, env.clone(), fd_filestat_get), - "fd_filestat_set_size" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native_with_env(store, env.clone(), fd_filestat_set_times), - "fd_pread" => Function::new_native_with_env(store, env.clone(), fd_pread), - "fd_prestat_get" => Function::new_native_with_env(store, env.clone(), fd_prestat_get), - "fd_prestat_dir_name" => Function::new_native_with_env(store, env.clone(), fd_prestat_dir_name), - "fd_pwrite" => Function::new_native_with_env(store, env.clone(), fd_pwrite), - "fd_read" => Function::new_native_with_env(store, env.clone(), fd_read), - "fd_readdir" => Function::new_native_with_env(store, env.clone(), fd_readdir), - "fd_renumber" => Function::new_native_with_env(store, env.clone(), fd_renumber), - "fd_dup" => Function::new_native_with_env(store, env.clone(), fd_dup), - "fd_event" => Function::new_native_with_env(store, env.clone(), fd_event), - "fd_seek" => Function::new_native_with_env(store, env.clone(), fd_seek), - "fd_sync" => Function::new_native_with_env(store, env.clone(), fd_sync), - "fd_tell" => Function::new_native_with_env(store, env.clone(), fd_tell), - "fd_write" => Function::new_native_with_env(store, env.clone(), fd_write), - "fd_pipe" => Function::new_native_with_env(store, env.clone(), fd_pipe), - "path_create_directory" => Function::new_native_with_env(store, env.clone(), path_create_directory), - "path_filestat_get" => Function::new_native_with_env(store, env.clone(), path_filestat_get), - "path_filestat_set_times" => Function::new_native_with_env(store, env.clone(), path_filestat_set_times), - "path_link" => Function::new_native_with_env(store, env.clone(), path_link), - "path_open" => Function::new_native_with_env(store, env.clone(), path_open), - "path_readlink" => Function::new_native_with_env(store, env.clone(), path_readlink), - "path_remove_directory" => Function::new_native_with_env(store, env.clone(), path_remove_directory), - "path_rename" => Function::new_native_with_env(store, env.clone(), path_rename), - "path_symlink" => Function::new_native_with_env(store, env.clone(), path_symlink), - "path_unlink_file" => Function::new_native_with_env(store, env.clone(), path_unlink_file), - "poll_oneoff" => Function::new_native_with_env(store, env.clone(), poll_oneoff), - "proc_exit" => Function::new_native_with_env(store, env.clone(), proc_exit), - "proc_raise" => Function::new_native_with_env(store, env.clone(), proc_raise), - "random_get" => Function::new_native_with_env(store, env.clone(), random_get), - "tty_get" => Function::new_native_with_env(store, env.clone(), tty_get), - "tty_set" => Function::new_native_with_env(store, env.clone(), tty_set), - "getcwd" => Function::new_native_with_env(store, env.clone(), getcwd), - "chdir" => Function::new_native_with_env(store, env.clone(), chdir), - "thread_spawn" => Function::new_native_with_env(store, env.clone(), thread_spawn), - "thread_sleep" => Function::new_native_with_env(store, env.clone(), thread_sleep), - "thread_id" => Function::new_native_with_env(store, env.clone(), thread_id), - "thread_join" => Function::new_native_with_env(store, env.clone(), thread_join), - "thread_parallelism" => Function::new_native_with_env(store, env.clone(), thread_parallelism), - "thread_exit" => Function::new_native_with_env(store, env.clone(), thread_exit), - "sched_yield" => Function::new_native_with_env(store, env.clone(), sched_yield), - "getpid" => Function::new_native_with_env(store, env.clone(), getpid), - "process_spawn" => Function::new_native_with_env(store, env.clone(), process_spawn), - "bus_open_local" => Function::new_native_with_env(store, env.clone(), bus_open_local), - "bus_open_remote" => Function::new_native_with_env(store, env.clone(), bus_open_remote), - "bus_close" => Function::new_native_with_env(store, env.clone(), bus_close), - "bus_call" => Function::new_native_with_env(store, env.clone(), bus_call), - "bus_subcall" => Function::new_native_with_env(store, env.clone(), bus_subcall), - "bus_poll" => Function::new_native_with_env(store, env.clone(), bus_poll), - "call_reply" => Function::new_native_with_env(store, env.clone(), call_reply), - "call_fault" => Function::new_native_with_env(store, env.clone(), call_fault), - "call_close" => Function::new_native_with_env(store, env.clone(), call_close), - "ws_connect" => Function::new_native_with_env(store, env.clone(), ws_connect), - "http_request" => Function::new_native_with_env(store, env.clone(), http_request), - "http_status" => Function::new_native_with_env(store, env.clone(), http_status), - "port_bridge" => Function::new_native_with_env(store, env.clone(), port_bridge), - "port_unbridge" => Function::new_native_with_env(store, env.clone(), port_unbridge), - "port_dhcp_acquire" => Function::new_native_with_env(store, env.clone(), port_dhcp_acquire), - "port_addr_add" => Function::new_native_with_env(store, env.clone(), port_addr_add), - "port_addr_remove" => Function::new_native_with_env(store, env.clone(), port_addr_remove), - "port_addr_clear" => Function::new_native_with_env(store, env.clone(), port_addr_clear), - "port_addr_list" => Function::new_native_with_env(store, env.clone(), port_addr_list), - "port_mac" => Function::new_native_with_env(store, env.clone(), port_mac), - "port_gateway_set" => Function::new_native_with_env(store, env.clone(), port_gateway_set), - "port_route_add" => Function::new_native_with_env(store, env.clone(), port_route_add), - "port_route_remove" => Function::new_native_with_env(store, env.clone(), port_route_remove), - "port_route_clear" => Function::new_native_with_env(store, env.clone(), port_route_clear), - "port_route_list" => Function::new_native_with_env(store, env.clone(), port_route_list), - "sock_status" => Function::new_native_with_env(store, env.clone(), sock_status), - "sock_addr_local" => Function::new_native_with_env(store, env.clone(), sock_addr_local), - "sock_addr_peer" => Function::new_native_with_env(store, env.clone(), sock_addr_peer), - "sock_open" => Function::new_native_with_env(store, env.clone(), sock_open), - "sock_set_opt_flag" => Function::new_native_with_env(store, env.clone(), sock_set_opt_flag), - "sock_get_opt_flag" => Function::new_native_with_env(store, env.clone(), sock_get_opt_flag), - "sock_set_opt_time" => Function::new_native_with_env(store, env.clone(), sock_set_opt_time), - "sock_get_opt_time" => Function::new_native_with_env(store, env.clone(), sock_get_opt_time), - "sock_set_opt_size" => Function::new_native_with_env(store, env.clone(), sock_set_opt_size), - "sock_get_opt_size" => Function::new_native_with_env(store, env.clone(), sock_get_opt_size), - "sock_join_multicast_v4" => Function::new_native_with_env(store, env.clone(), sock_join_multicast_v4), - "sock_leave_multicast_v4" => Function::new_native_with_env(store, env.clone(), sock_leave_multicast_v4), - "sock_join_multicast_v6" => Function::new_native_with_env(store, env.clone(), sock_join_multicast_v6), - "sock_leave_multicast_v6" => Function::new_native_with_env(store, env.clone(), sock_leave_multicast_v6), - "sock_bind" => Function::new_native_with_env(store, env.clone(), sock_bind), - "sock_listen" => Function::new_native_with_env(store, env.clone(), sock_listen), - "sock_accept" => Function::new_native_with_env(store, env.clone(), sock_accept), - "sock_connect" => Function::new_native_with_env(store, env.clone(), sock_connect), - "sock_recv" => Function::new_native_with_env(store, env.clone(), sock_recv), - "sock_recv_from" => Function::new_native_with_env(store, env.clone(), sock_recv_from), - "sock_send" => Function::new_native_with_env(store, env.clone(), sock_send), - "sock_send_to" => Function::new_native_with_env(store, env.clone(), sock_send_to), - "sock_send_file" => Function::new_native_with_env(store, env.clone(), sock_send_file), - "sock_shutdown" => Function::new_native_with_env(store, env.clone(), sock_shutdown), - "resolve" => Function::new_native_with_env(store, env, resolve), + "args_get" => Function::new_native(ctx, args_get), + "args_sizes_get" => Function::new_native(ctx, args_sizes_get), + "clock_res_get" => Function::new_native(ctx, clock_res_get), + "clock_time_get" => Function::new_native(ctx, clock_time_get), + "environ_get" => Function::new_native(ctx, environ_get), + "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get), + "fd_advise" => Function::new_native(ctx, fd_advise), + "fd_allocate" => Function::new_native(ctx, fd_allocate), + "fd_close" => Function::new_native(ctx, fd_close), + "fd_datasync" => Function::new_native(ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get), + "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(ctx, fd_filestat_get), + "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(ctx, fd_pread), + "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get), + "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name), + "fd_pwrite" => Function::new_native(ctx, fd_pwrite), + "fd_read" => Function::new_native(ctx, fd_read), + "fd_readdir" => Function::new_native(ctx, fd_readdir), + "fd_renumber" => Function::new_native(ctx, fd_renumber), + "fd_dup" => Function::new_native(ctx, fd_dup), + "fd_event" => Function::new_native(ctx, fd_event), + "fd_seek" => Function::new_native(ctx, fd_seek), + "fd_sync" => Function::new_native(ctx, fd_sync), + "fd_tell" => Function::new_native(ctx, fd_tell), + "fd_write" => Function::new_native(ctx, fd_write), + "fd_pipe" => Function::new_native(ctx, fd_pipe), + "path_create_directory" => Function::new_native(ctx, path_create_directory), + "path_filestat_get" => Function::new_native(ctx, path_filestat_get), + "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times), + "path_link" => Function::new_native(ctx, path_link), + "path_open" => Function::new_native(ctx, path_open), + "path_readlink" => Function::new_native(ctx, path_readlink), + "path_remove_directory" => Function::new_native(ctx, path_remove_directory), + "path_rename" => Function::new_native(ctx, path_rename), + "path_symlink" => Function::new_native(ctx, path_symlink), + "path_unlink_file" => Function::new_native(ctx, path_unlink_file), + "poll_oneoff" => Function::new_native(ctx, poll_oneoff), + "proc_exit" => Function::new_native(ctx, proc_exit), + "proc_raise" => Function::new_native(ctx, proc_raise), + "random_get" => Function::new_native(ctx, random_get), + "tty_get" => Function::new_native(ctx, tty_get), + "tty_set" => Function::new_native(ctx, tty_set), + "getcwd" => Function::new_native(ctx, getcwd), + "chdir" => Function::new_native(ctx, chdir), + "thread_spawn" => Function::new_native(ctx, thread_spawn), + "thread_sleep" => Function::new_native(ctx, thread_sleep), + "thread_id" => Function::new_native(ctx, thread_id), + "thread_join" => Function::new_native(ctx, thread_join), + "thread_parallelism" => Function::new_native(ctx, thread_parallelism), + "thread_exit" => Function::new_native(ctx, thread_exit), + "sched_yield" => Function::new_native(ctx, sched_yield), + "getpid" => Function::new_native(ctx, getpid), + "process_spawn" => Function::new_native(ctx, process_spawn), + "bus_open_local" => Function::new_native(ctx, bus_open_local), + "bus_open_remote" => Function::new_native(ctx, bus_open_remote), + "bus_close" => Function::new_native(ctx, bus_close), + "bus_call" => Function::new_native(ctx, bus_call), + "bus_subcall" => Function::new_native(ctx, bus_subcall), + "bus_poll" => Function::new_native(ctx, bus_poll), + "call_reply" => Function::new_native(ctx, call_reply), + "call_fault" => Function::new_native(ctx, call_fault), + "call_close" => Function::new_native(ctx, call_close), + "ws_connect" => Function::new_native(ctx, ws_connect), + "http_request" => Function::new_native(ctx, http_request), + "http_status" => Function::new_native(ctx, http_status), + "port_bridge" => Function::new_native(ctx, port_bridge), + "port_unbridge" => Function::new_native(ctx, port_unbridge), + "port_dhcp_acquire" => Function::new_native(ctx, port_dhcp_acquire), + "port_addr_add" => Function::new_native(ctx, port_addr_add), + "port_addr_remove" => Function::new_native(ctx, port_addr_remove), + "port_addr_clear" => Function::new_native(ctx, port_addr_clear), + "port_addr_list" => Function::new_native(ctx, port_addr_list), + "port_mac" => Function::new_native(ctx, port_mac), + "port_gateway_set" => Function::new_native(ctx, port_gateway_set), + "port_route_add" => Function::new_native(ctx, port_route_add), + "port_route_remove" => Function::new_native(ctx, port_route_remove), + "port_route_clear" => Function::new_native(ctx, port_route_clear), + "port_route_list" => Function::new_native(ctx, port_route_list), + "sock_status" => Function::new_native(ctx, sock_status), + "sock_addr_local" => Function::new_native(ctx, sock_addr_local), + "sock_addr_peer" => Function::new_native(ctx, sock_addr_peer), + "sock_open" => Function::new_native(ctx, sock_open), + "sock_set_opt_flag" => Function::new_native(ctx, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_native(ctx, sock_get_opt_flag), + "sock_set_opt_time" => Function::new_native(ctx, sock_set_opt_time), + "sock_get_opt_time" => Function::new_native(ctx, sock_get_opt_time), + "sock_set_opt_size" => Function::new_native(ctx, sock_set_opt_size), + "sock_get_opt_size" => Function::new_native(ctx, sock_get_opt_size), + "sock_join_multicast_v4" => Function::new_native(ctx, sock_join_multicast_v4), + "sock_leave_multicast_v4" => Function::new_native(ctx, sock_leave_multicast_v4), + "sock_join_multicast_v6" => Function::new_native(ctx, sock_join_multicast_v6), + "sock_leave_multicast_v6" => Function::new_native(ctx, sock_leave_multicast_v6), + "sock_bind" => Function::new_native(ctx, sock_bind), + "sock_listen" => Function::new_native(ctx, sock_listen), + "sock_accept" => Function::new_native(ctx, sock_accept), + "sock_connect" => Function::new_native(ctx, sock_connect), + "sock_recv" => Function::new_native(ctx, sock_recv), + "sock_recv_from" => Function::new_native(ctx, sock_recv_from), + "sock_send" => Function::new_native(ctx, sock_send), + "sock_send_to" => Function::new_native(ctx, sock_send_to), + "sock_send_file" => Function::new_native(ctx, sock_send_file), + "sock_shutdown" => Function::new_native(ctx, sock_shutdown), + "resolve" => Function::new_native(ctx, resolve), } } } diff --git a/lib/wasi/src/macros.rs b/lib/wasi/src/macros.rs index b9ec4245597..bd6e6566d41 100644 --- a/lib/wasi/src/macros.rs +++ b/lib/wasi/src/macros.rs @@ -98,13 +98,13 @@ macro_rules! wasi_try_mem_ok { /// Reads a string from Wasm memory. macro_rules! get_input_str { - ($memory:expr, $data:expr, $len:expr) => {{ - wasi_try_mem!($data.read_utf8_string($memory, $len)) + ($ctx:expr, $memory:expr, $data:expr, $len:expr) => {{ + wasi_try_mem!($data.read_utf8_string($ctx, $memory, $len)) }}; } macro_rules! get_input_str_bus { - ($memory:expr, $data:expr, $len:expr) => {{ - wasi_try_mem_bus!($data.read_utf8_string($memory, $len)) + ($ctx:expr, $memory:expr, $data:expr, $len:expr) => {{ + wasi_try_mem_bus!($data.read_utf8_string($ctx, $memory, $len)) }}; } diff --git a/lib/wasi/src/state/pipe.rs b/lib/wasi/src/state/pipe.rs index b49e4040812..29ccb9373ba 100644 --- a/lib/wasi/src/state/pipe.rs +++ b/lib/wasi/src/state/pipe.rs @@ -1,5 +1,6 @@ use crate::syscalls::types::*; use crate::syscalls::{read_bytes, write_bytes}; +use crate::WasiEnv; use bytes::{Buf, Bytes}; use std::convert::TryInto; use std::io::{self, Read}; @@ -7,7 +8,7 @@ use std::ops::DerefMut; use std::sync::mpsc; use std::sync::Mutex; use wasmer::MemorySize; -use wasmer::{Memory, WasmSlice}; +use wasmer::{ContextMut, Memory, WasmSlice}; #[derive(Debug)] pub struct WasiPipe { @@ -41,6 +42,7 @@ impl WasiPipe { pub fn recv( &mut self, + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_iovec_t>, ) -> Result { @@ -49,7 +51,7 @@ impl WasiPipe { let buf_len = buf.len(); if buf_len > 0 { let reader = buf.as_ref(); - let read = read_bytes(reader, memory, iov).map(|_| buf_len as usize)?; + let read = read_bytes(ctx, reader, memory, iov).map(|_| buf_len as usize)?; buf.advance(read); return Ok(read); } @@ -62,6 +64,7 @@ impl WasiPipe { pub fn send( &mut self, + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_ciovec_t>, ) -> Result { @@ -72,7 +75,7 @@ impl WasiPipe { .sum(); let buf_len: usize = buf_len.try_into().map_err(|_| __WASI_EINVAL)?; let mut buf = Vec::with_capacity(buf_len); - write_bytes(&mut buf, memory, iov)?; + write_bytes(ctx, &mut buf, memory, iov)?; let tx = self.tx.lock().unwrap(); tx.send(buf).map_err(|_| __WASI_EIO)?; Ok(buf_len) diff --git a/lib/wasi/src/state/socket.rs b/lib/wasi/src/state/socket.rs index 290b154b766..d2ab0e7ae6a 100644 --- a/lib/wasi/src/state/socket.rs +++ b/lib/wasi/src/state/socket.rs @@ -1,6 +1,7 @@ use super::types::net_error_into_wasi_err; use crate::syscalls::types::*; use crate::syscalls::{read_bytes, write_bytes}; +use crate::WasiEnv; use bytes::{Buf, Bytes}; use std::convert::TryInto; use std::io::{self, Read}; @@ -10,7 +11,7 @@ use std::sync::Mutex; use std::time::Duration; #[allow(unused_imports)] use tracing::{debug, error, info, warn}; -use wasmer::{Memory, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{ContextMut, Memory, MemorySize, WasmPtr, WasmSlice}; use wasmer_vnet::{net_error_into_io_err, TimeType}; use wasmer_vnet::{ IpCidr, IpRoute, SocketHttpRequest, VirtualIcmpSocket, VirtualNetworking, VirtualRawSocket, @@ -768,6 +769,7 @@ impl InodeSocket { pub fn send( &mut self, + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_ciovec_t>, ) -> Result { @@ -778,7 +780,7 @@ impl InodeSocket { .sum(); let buf_len: usize = buf_len.try_into().map_err(|_| __WASI_EINVAL)?; let mut buf = Vec::with_capacity(buf_len); - write_bytes(&mut buf, memory, iov)?; + write_bytes(ctx, &mut buf, memory, iov)?; match &mut self.kind { InodeSocketKind::HttpRequest(sock, ty) => { let sock = sock.get_mut().unwrap(); @@ -852,11 +854,12 @@ impl InodeSocket { pub fn send_to( &mut self, + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_ciovec_t>, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> Result { - let (addr_ip, addr_port) = read_ip_port(memory, addr)?; + let (addr_ip, addr_port) = read_ip_port(ctx, memory, addr)?; let addr = SocketAddr::new(addr_ip, addr_port); let buf_len: M::Offset = iov .iter() @@ -865,7 +868,7 @@ impl InodeSocket { .sum(); let buf_len: usize = buf_len.try_into().map_err(|_| __WASI_EINVAL)?; let mut buf = Vec::with_capacity(buf_len); - write_bytes(&mut buf, memory, iov)?; + write_bytes(ctx, &mut buf, memory, iov)?; match &mut self.kind { InodeSocketKind::Icmp(sock) => sock .send_to(Bytes::from(buf), addr) @@ -882,6 +885,7 @@ impl InodeSocket { pub fn recv( &mut self, + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_iovec_t>, ) -> Result { @@ -890,7 +894,7 @@ impl InodeSocket { let buf_len = buf.len(); if buf_len > 0 { let reader = buf.as_ref(); - let read = read_bytes(reader, memory, iov).map(|_| buf_len)?; + let read = read_bytes(ctx, reader, memory, iov).map(|_| buf_len)?; if let InodeSocketKind::TcpStream(..) = &self.kind { buf.advance(read); } else { @@ -951,6 +955,7 @@ impl InodeSocket { pub fn recv_from( &mut self, + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_iovec_t>, addr: WasmPtr<__wasi_addr_port_t, M>, @@ -959,11 +964,11 @@ impl InodeSocket { if let Some(buf) = self.read_buffer.as_mut() { if !buf.is_empty() { let reader = buf.as_ref(); - let ret = read_bytes(reader, memory, iov)?; + let ret = read_bytes(ctx, reader, memory, iov)?; let peer = self .read_addr .unwrap_or_else(|| SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)); - write_ip_port(memory, addr, peer.ip(), peer.port())?; + write_ip_port(ctx, memory, addr, peer.ip(), peer.port())?; return Ok(ret); } } @@ -1130,10 +1135,11 @@ impl Drop for InodeSocket { #[allow(dead_code)] pub(crate) fn read_ip( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_addr_t, M>, ) -> Result { - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.u.octs; @@ -1148,10 +1154,11 @@ pub(crate) fn read_ip( } pub(crate) fn read_ip_v4( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_addr_ip4_t, M>, ) -> Result { - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.octs; @@ -1159,10 +1166,11 @@ pub(crate) fn read_ip_v4( } pub(crate) fn read_ip_v6( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_addr_ip6_t, M>, ) -> Result { - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(addr.segs) }; @@ -1170,6 +1178,7 @@ pub(crate) fn read_ip_v6( } pub(crate) fn write_ip( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_addr_t, M>, ip: IpAddr, @@ -1193,17 +1202,18 @@ pub(crate) fn write_ip( } }; - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); addr_ptr.write(ip).map_err(crate::mem_error_to_wasi)?; Ok(()) } #[allow(dead_code)] pub(crate) fn read_cidr( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_cidr_t, M>, ) -> Result { - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.u.octs; @@ -1231,6 +1241,7 @@ pub(crate) fn read_cidr( #[allow(dead_code)] pub(crate) fn write_cidr( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_cidr_t, M>, cidr: IpCidr, @@ -1262,16 +1273,17 @@ pub(crate) fn write_cidr( } }; - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); addr_ptr.write(cidr).map_err(crate::mem_error_to_wasi)?; Ok(()) } pub(crate) fn read_ip_port( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_addr_port_t, M>, ) -> Result<(IpAddr, u16), __wasi_errno_t> { - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); let addr = addr_ptr.read().map_err(crate::mem_error_to_wasi)?; let o = addr.u.octs; @@ -1299,6 +1311,7 @@ pub(crate) fn read_ip_port( #[allow(dead_code)] pub(crate) fn write_ip_port( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_addr_port_t, M>, ip: IpAddr, @@ -1331,17 +1344,18 @@ pub(crate) fn write_ip_port( } }; - let addr_ptr = ptr.deref(memory); + let addr_ptr = ptr.deref(ctx, memory); addr_ptr.write(ipport).map_err(crate::mem_error_to_wasi)?; Ok(()) } #[allow(dead_code)] pub(crate) fn read_route( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_route_t, M>, ) -> Result { - let route_ptr = ptr.deref(memory); + let route_ptr = ptr.deref(ctx, memory); let route = route_ptr.read().map_err(crate::mem_error_to_wasi)?; Ok(IpRoute { @@ -1393,6 +1407,7 @@ pub(crate) fn read_route( } pub(crate) fn write_route( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, ptr: WasmPtr<__wasi_route_t, M>, route: IpRoute, @@ -1471,7 +1486,7 @@ pub(crate) fn write_route( expires_at, }; - let route_ptr = ptr.deref(memory); + let route_ptr = ptr.deref(ctx, memory); route_ptr.write(route).map_err(crate::mem_error_to_wasi)?; Ok(()) } diff --git a/lib/wasi/src/syscalls/legacy/snapshot0.rs b/lib/wasi/src/syscalls/legacy/snapshot0.rs index bf15b211966..96a1eed7090 100644 --- a/lib/wasi/src/syscalls/legacy/snapshot0.rs +++ b/lib/wasi/src/syscalls/legacy/snapshot0.rs @@ -1,7 +1,7 @@ use crate::syscalls; use crate::syscalls::types::{self, snapshot0}; use crate::{mem_error_to_wasi, Memory32, MemorySize, WasiEnv, WasiError, WasiThread}; -use wasmer::WasmPtr; +use wasmer::{AsContextMut, ContextMut, WasmPtr}; /// Wrapper around `syscalls::fd_filestat_get` with extra logic to handle the size /// difference of `wasi_filestat_t` @@ -10,10 +10,11 @@ use wasmer::WasmPtr; /// Wasm memory. If the memory clobbered by the current syscall is also used by /// that syscall, then it may break. pub fn fd_filestat_get( - env: &WasiEnv, + mut ctx: ContextMut<'_, WasiEnv>, fd: types::__wasi_fd_t, buf: WasmPtr, ) -> types::__wasi_errno_t { + let env = ctx.data(); let memory = env.memory(); // transmute the WasmPtr into a WasmPtr where T2 > T1, this will read extra memory. @@ -22,17 +23,18 @@ pub fn fd_filestat_get( let new_buf: WasmPtr = buf.cast(); // Copy the data including the extra data - let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(memory)); + let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(&ctx, memory)); // Set up complete, make the call with the pointer that will write to the // struct and some unrelated memory after the struct. - let result = syscalls::fd_filestat_get::(env, fd, new_buf); + let result = syscalls::fd_filestat_get::(ctx.as_context_mut(), fd, new_buf); // reborrow memory + let env = ctx.data(); let memory = env.memory(); // get the values written to memory - let new_filestat = wasi_try_mem!(new_buf.deref(memory).read()); + let new_filestat = wasi_try_mem!(new_buf.deref(&ctx, memory).read()); // translate the new struct into the old struct in host memory let old_stat = snapshot0::__wasi_filestat_t { st_dev: new_filestat.st_dev, @@ -47,11 +49,11 @@ pub fn fd_filestat_get( // write back the original values at the pointer's memory locations // (including the memory unrelated to the pointer) - wasi_try_mem!(new_buf.deref(memory).write(new_filestat_setup)); + wasi_try_mem!(new_buf.deref(&ctx, memory).write(new_filestat_setup)); // Now that this memory is back as it was, write the translated filestat // into memory leaving it as it should be - wasi_try_mem!(buf.deref(memory).write(old_stat)); + wasi_try_mem!(buf.deref(&ctx, memory).write(old_stat)); result } @@ -59,7 +61,7 @@ pub fn fd_filestat_get( /// Wrapper around `syscalls::path_filestat_get` with extra logic to handle the size /// difference of `wasi_filestat_t` pub fn path_filestat_get( - env: &WasiEnv, + mut ctx: ContextMut<'_, WasiEnv>, fd: types::__wasi_fd_t, flags: types::__wasi_lookupflags_t, path: WasmPtr, @@ -67,15 +69,25 @@ pub fn path_filestat_get( buf: WasmPtr, ) -> types::__wasi_errno_t { // see `fd_filestat_get` in this file for an explanation of this strange behavior + let env = ctx.data(); let memory = env.memory(); let new_buf: WasmPtr = buf.cast(); - let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(memory)); - - let result = syscalls::path_filestat_get::(env, fd, flags, path, path_len, new_buf); - + let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(&ctx, memory)); + + let result = syscalls::path_filestat_get::( + ctx.as_context_mut(), + fd, + flags, + path, + path_len, + new_buf, + ); + + // need to re-borrow + let env = ctx.data(); let memory = env.memory(); - let new_filestat = wasi_try_mem!(new_buf.deref(memory).read()); + let new_filestat = wasi_try_mem!(new_buf.deref(&ctx, memory).read()); let old_stat = snapshot0::__wasi_filestat_t { st_dev: new_filestat.st_dev, st_ino: new_filestat.st_ino, @@ -87,8 +99,8 @@ pub fn path_filestat_get( st_ctim: new_filestat.st_ctim, }; - wasi_try_mem!(new_buf.deref(memory).write(new_filestat_setup)); - wasi_try_mem!(buf.deref(memory).write(old_stat)); + wasi_try_mem!(new_buf.deref(&ctx, memory).write(new_filestat_setup)); + wasi_try_mem!(buf.deref(&ctx, memory).write(old_stat)); result } @@ -96,7 +108,7 @@ pub fn path_filestat_get( /// Wrapper around `syscalls::fd_seek` with extra logic to remap the values /// of `__wasi_whence_t` pub fn fd_seek( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: types::__wasi_fd_t, offset: types::__wasi_filedelta_t, whence: snapshot0::__wasi_whence_t, @@ -109,13 +121,13 @@ pub fn fd_seek( // if it's invalid, let the new fd_seek handle it _ => whence, }; - syscalls::fd_seek::(env, fd, offset, new_whence, newoffset) + syscalls::fd_seek::(ctx, fd, offset, new_whence, newoffset) } /// Wrapper around `syscalls::poll_oneoff` with extra logic to add the removed /// userdata field back pub fn poll_oneoff( - env: &WasiEnv, + mut ctx: ContextMut<'_, WasiEnv>, in_: WasmPtr, out_: WasmPtr, nsubscriptions: u32, @@ -125,17 +137,19 @@ pub fn poll_oneoff( // we just need to readjust and copy it // we start by adjusting `in_` into a format that the new code can understand + let env = ctx.data(); let memory = env.memory(); let nsubscriptions_offset: u32 = nsubscriptions; - let in_origs = wasi_try_mem_ok!(in_.slice(memory, nsubscriptions_offset)); + let in_origs = wasi_try_mem_ok!(in_.slice(&ctx, memory, nsubscriptions_offset)); let in_origs = wasi_try_mem_ok!(in_origs.read_to_vec()); // get a pointer to the smaller new type let in_new_type_ptr: WasmPtr = in_.cast(); - for (in_sub_new, orig) in wasi_try_mem_ok!(in_new_type_ptr.slice(memory, nsubscriptions_offset)) - .iter() - .zip(in_origs.iter()) + for (in_sub_new, orig) in + wasi_try_mem_ok!(in_new_type_ptr.slice(&ctx, memory, nsubscriptions_offset)) + .iter() + .zip(in_origs.iter()) { wasi_try_mem_ok!(in_sub_new.write(types::__wasi_subscription_t { userdata: orig.userdata, @@ -158,13 +172,19 @@ pub fn poll_oneoff( } // make the call - let result = - syscalls::poll_oneoff::(env, in_new_type_ptr, out_, nsubscriptions, nevents); + let result = syscalls::poll_oneoff::( + ctx.as_context_mut(), + in_new_type_ptr, + out_, + nsubscriptions, + nevents, + ); // replace the old values of in, in case the calling code reuses the memory + let env = ctx.data(); let memory = env.memory(); - for (in_sub, orig) in wasi_try_mem_ok!(in_.slice(memory, nsubscriptions_offset)) + for (in_sub, orig) in wasi_try_mem_ok!(in_.slice(&ctx, memory, nsubscriptions_offset)) .iter() .zip(in_origs.into_iter()) { diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 54812ad292b..1c2e04f3b11 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -17,7 +17,7 @@ pub mod wasm32; pub mod windows; pub mod legacy; -pub mod wasi; +//pub mod wasi; pub mod wasix32; pub mod wasix64; @@ -46,7 +46,10 @@ use std::sync::{atomic::Ordering, Mutex}; use std::sync::{mpsc, Arc}; use std::time::Duration; use tracing::{debug, error, trace, warn}; -use wasmer::{Memory, Memory32, Memory64, MemorySize, RuntimeError, Value, WasmPtr, WasmSlice}; +use wasmer::{ + AsContextMut, ContextMut, Memory, Memory32, Memory64, MemorySize, RuntimeError, Value, WasmPtr, + WasmSlice, +}; use wasmer_vbus::{FileDescriptor, StdioMode}; use wasmer_vfs::{FsError, VirtualFile}; use wasmer_vnet::{SocketHttpRequest, StreamSecurity}; @@ -76,6 +79,7 @@ fn from_offset(offset: M::Offset) -> Result( + ctx: &ContextMut<'_, WasiEnv>, mut write_loc: T, memory: &Memory, iovs_arr_cell: WasmSlice<__wasi_ciovec_t>, @@ -84,7 +88,7 @@ fn write_bytes_inner( for iov in iovs_arr_cell.iter() { let iov_inner = iov.read().map_err(mem_error_to_wasi)?; let bytes = WasmPtr::::new(iov_inner.buf) - .slice(memory, iov_inner.buf_len) + .slice(ctx, memory, iov_inner.buf_len) .map_err(mem_error_to_wasi)?; let bytes = bytes.read_to_vec().map_err(mem_error_to_wasi)?; write_loc.write_all(&bytes).map_err(map_io_err)?; @@ -95,16 +99,18 @@ fn write_bytes_inner( } pub(crate) fn write_bytes( + ctx: &ContextMut<'_, WasiEnv>, mut write_loc: T, memory: &Memory, iovs_arr: WasmSlice<__wasi_ciovec_t>, ) -> Result { - let result = write_bytes_inner::<_, M>(&mut write_loc, memory, iovs_arr); + let result = write_bytes_inner::<_, M>(ctx, &mut write_loc, memory, iovs_arr); write_loc.flush(); result } pub(crate) fn read_bytes( + ctx: &ContextMut<'_, WasiEnv>, mut reader: T, memory: &Memory, iovs_arr: WasmSlice<__wasi_iovec_t>, @@ -122,7 +128,7 @@ pub(crate) fn read_bytes( bytes_read += reader.read(&mut raw_bytes).map_err(map_io_err)?; let buf = WasmPtr::::new(iov_inner.buf) - .slice(memory, iov_inner.buf_len) + .slice(ctx, memory, iov_inner.buf_len) .map_err(mem_error_to_wasi)?; buf.write_slice(&raw_bytes).map_err(mem_error_to_wasi)?; } @@ -135,7 +141,7 @@ fn has_rights(rights_set: __wasi_rights_t, rights_check_set: __wasi_rights_t) -> } fn __sock_actor( - env: &WasiEnv, + ctx: &ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, rights: __wasi_rights_t, actor: F, @@ -143,6 +149,7 @@ fn __sock_actor( where F: FnOnce(&crate::state::InodeSocket) -> Result, { + let env = ctx.data(); let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = state.fs.get_fd(sock)?; @@ -167,7 +174,7 @@ where } fn __sock_actor_mut( - env: &WasiEnv, + ctx: &ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, rights: __wasi_rights_t, actor: F, @@ -175,6 +182,7 @@ fn __sock_actor_mut( where F: FnOnce(&mut crate::state::InodeSocket) -> Result, { + let env = ctx.data(); let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = state.fs.get_fd(sock)?; @@ -199,7 +207,7 @@ where } fn __sock_upgrade( - env: &WasiEnv, + ctx: &ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, rights: __wasi_rights_t, actor: F, @@ -209,6 +217,7 @@ where &mut crate::state::InodeSocket, ) -> Result, __wasi_errno_t>, { + let env = ctx.data(); let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = state.fs.get_fd(sock)?; @@ -238,12 +247,15 @@ where #[must_use] fn write_buffer_array( + ctx: &ContextMut<'_, WasiEnv>, memory: &Memory, from: &[Vec], ptr_buffer: WasmPtr, M>, buffer: WasmPtr, ) -> __wasi_errno_t { - let ptrs = wasi_try_mem!(ptr_buffer.slice(memory, wasi_try!(to_offset::(from.len())))); + let env = ctx.data(); + let memory = env.memory(); + let ptrs = wasi_try_mem!(ptr_buffer.slice(ctx, memory, wasi_try!(to_offset::(from.len())))); let mut current_buffer_offset = 0usize; for ((i, sub_buffer), ptr) in from.iter().enumerate().zip(ptrs.iter()) { @@ -254,12 +266,12 @@ fn write_buffer_array( wasi_try_mem!(ptr.write(new_ptr)); let data = - wasi_try_mem!(new_ptr.slice(memory, wasi_try!(to_offset::(sub_buffer.len())))); + wasi_try_mem!(new_ptr.slice(ctx, memory, wasi_try!(to_offset::(sub_buffer.len())))); wasi_try_mem!(data.write_slice(sub_buffer)); wasi_try_mem!(wasi_try_mem!( new_ptr.add_offset(wasi_try!(to_offset::(sub_buffer.len()))) ) - .write(memory, 0)); + .write(ctx, memory, 0)); current_buffer_offset += sub_buffer.len() + 1; } @@ -285,14 +297,15 @@ fn get_current_time_in_nanos() -> Result<__wasi_timestamp_t, __wasi_errno_t> { /// A pointer to a buffer to write the argument string data. /// pub fn args_get( - env: &WasiEnv, + mut ctx: ContextMut<'_, WasiEnv>, argv: WasmPtr, M>, argv_buf: WasmPtr, ) -> __wasi_errno_t { debug!("wasi::args_get"); - let (memory, state) = env.get_memory_and_wasi_state(0); + let env = ctx.data(); + let (memory, mut state) = env.get_memory_and_wasi_state(0); - let result = write_buffer_array(memory, &*state.args, argv, argv_buf); + let result = write_buffer_array(&ctx, memory, &*state.args, argv, argv_buf); debug!( "=> args:\n{}", @@ -316,15 +329,16 @@ pub fn args_get( /// - `size_t *argv_buf_size` /// The size of the argument string data. pub fn args_sizes_get( - env: &WasiEnv, + mut ctx: ContextMut<'_, WasiEnv>, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { debug!("wasi::args_sizes_get"); - let (memory, state) = env.get_memory_and_wasi_state(0); + let env = ctx.data(); + let (memory, mut state) = env.get_memory_and_wasi_state(0); - let argc = argc.deref(memory); - let argv_buf_size = argv_buf_size.deref(memory); + let argc = argc.deref(&ctx, memory); + let argv_buf_size = argv_buf_size.deref(&ctx, memory); let argc_val: M::Offset = wasi_try!(state.args.len().try_into().map_err(|_| __WASI_EOVERFLOW)); let argv_buf_size_val: usize = state.args.iter().map(|v| v.len() + 1).sum(); @@ -347,16 +361,17 @@ pub fn args_sizes_get( /// - `__wasi_timestamp_t *resolution` /// The resolution of the clock in nanoseconds pub fn clock_res_get( - env: &WasiEnv, + mut ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, M>, ) -> __wasi_errno_t { trace!("wasi::clock_res_get"); + let env = ctx.data(); let memory = env.memory(); - let out_addr = resolution.deref(memory); + let out_addr = resolution.deref(&ctx, memory); let t_out = wasi_try!(platform_clock_res_get(clock_id, out_addr)); - wasi_try_mem!(resolution.write(memory, t_out as __wasi_timestamp_t)); + wasi_try_mem!(resolution.write(&ctx, memory, t_out as __wasi_timestamp_t)); __WASI_ESUCCESS } @@ -371,7 +386,7 @@ pub fn clock_res_get( /// - `__wasi_timestamp_t *time` /// The value of the clock in nanoseconds pub fn clock_time_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, M>, @@ -380,15 +395,16 @@ pub fn clock_time_get( "wasi::clock_time_get clock_id: {}, precision: {}", clock_id, precision ); + let env = ctx.data(); let memory = env.memory(); let t_out = wasi_try!(platform_clock_time_get(clock_id, precision)); - wasi_try_mem!(time.write(memory, t_out as __wasi_timestamp_t)); + wasi_try_mem!(time.write(&ctx, memory, t_out as __wasi_timestamp_t)); let result = __WASI_ESUCCESS; trace!( "time: {} => {}", - wasi_try_mem!(time.deref(memory).read()), + wasi_try_mem!(time.deref(&ctx, memory).read()), result ); result @@ -403,7 +419,7 @@ pub fn clock_time_get( /// - `char *environ_buf` /// A pointer to a buffer to write the environment variable string data. pub fn environ_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ: WasmPtr, M>, environ_buf: WasmPtr, ) -> __wasi_errno_t { @@ -411,10 +427,11 @@ pub fn environ_get( "wasi::environ_get. Environ: {:?}, environ_buf: {:?}", environ, environ_buf ); - let (memory, state) = env.get_memory_and_wasi_state(0); + let env = ctx.data(); + let (memory, mut state) = env.get_memory_and_wasi_state(0); trace!(" -> State envs: {:?}", state.envs); - write_buffer_array(memory, &*state.envs, environ, environ_buf) + write_buffer_array(&ctx, memory, &*state.envs, environ, environ_buf) } /// ### `environ_sizes_get()` @@ -425,15 +442,16 @@ pub fn environ_get( /// - `size_t *environ_buf_size` /// The size of the environment variable string data. pub fn environ_sizes_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { trace!("wasi::environ_sizes_get"); - let (memory, state) = env.get_memory_and_wasi_state(0); + let env = ctx.data(); + let (memory, mut state) = env.get_memory_and_wasi_state(0); - let environ_count = environ_count.deref(memory); - let environ_buf_size = environ_buf_size.deref(memory); + let environ_count = environ_count.deref(&ctx, memory); + let environ_buf_size = environ_buf_size.deref(&ctx, memory); let env_var_count: M::Offset = wasi_try!(state.envs.len().try_into().map_err(|_| __WASI_EOVERFLOW)); @@ -463,7 +481,7 @@ pub fn environ_sizes_get( /// - `__wasi_advice_t advice` /// The advice to give pub fn fd_advise( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -486,13 +504,14 @@ pub fn fd_advise( /// - `__wasi_filesize_t len` /// The length from the offset marking the end of the allocation pub fn fd_allocate( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, ) -> __wasi_errno_t { debug!("wasi::fd_allocate"); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); let inode = fd_entry.inode; @@ -536,9 +555,10 @@ pub fn fd_allocate( /// If `fd` is a directory /// - `__WASI_EBADF` /// If `fd` is invalid or not open -pub fn fd_close(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_close: fd={}", fd); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); @@ -552,9 +572,10 @@ pub fn fd_close(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { /// Inputs: /// - `__wasi_fd_t fd` /// The file descriptor to sync -pub fn fd_datasync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_datasync"); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_DATASYNC) { return __WASI_EACCES; @@ -576,7 +597,7 @@ pub fn fd_datasync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { /// - `__wasi_fdstat_t *buf` /// The location where the metadata will be written pub fn fd_fdstat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, M>, ) -> __wasi_errno_t { @@ -585,10 +606,13 @@ pub fn fd_fdstat_get( fd, buf_ptr.offset() ); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let stat = wasi_try!(state.fs.fdstat(inodes.deref(), fd)); - wasi_try_mem!(buf_ptr.write(memory, stat)); + let buf = buf_ptr.deref(&ctx, memory); + + wasi_try_mem!(buf.write(stat)); __WASI_ESUCCESS } @@ -601,12 +625,13 @@ pub fn fd_fdstat_get( /// - `__wasi_fdflags_t flags` /// The flags to apply to `fd` pub fn fd_fdstat_set_flags( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { debug!("wasi::fd_fdstat_set_flags"); - let (_, state) = env.get_memory_and_wasi_state(0); + let env = ctx.data(); + let (_, mut state) = env.get_memory_and_wasi_state(0); let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); @@ -628,13 +653,14 @@ pub fn fd_fdstat_set_flags( /// - `__wasi_rights_t fs_rights_inheriting` /// The inheriting rights to apply to `fd` pub fn fd_fdstat_set_rights( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, ) -> __wasi_errno_t { debug!("wasi::fd_fdstat_set_rights"); - let (_, state) = env.get_memory_and_wasi_state(0); + let env = ctx.data(); + let (_, mut state) = env.get_memory_and_wasi_state(0); let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try!(fd_map.get_mut(&fd).ok_or(__WASI_EBADF)); @@ -660,12 +686,13 @@ pub fn fd_fdstat_set_rights( /// - `__wasi_filestat_t *buf` /// Where the metadata from `fd` will be written pub fn fd_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, M>, ) -> __wasi_errno_t { debug!("wasi::fd_filestat_get"); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_FILESTAT_GET) { return __WASI_EACCES; @@ -673,7 +700,8 @@ pub fn fd_filestat_get( let stat = wasi_try!(state.fs.filestat_fd(inodes.deref(), fd)); - wasi_try_mem!(buf.write(memory, stat)); + let buf = buf.deref(&ctx, memory); + wasi_try_mem!(buf.write(stat)); __WASI_ESUCCESS } @@ -686,12 +714,13 @@ pub fn fd_filestat_get( /// - `__wasi_filesize_t st_size` /// New size that `fd` will be set to pub fn fd_filestat_set_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { debug!("wasi::fd_filestat_set_size"); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); let inode = fd_entry.inode; @@ -734,14 +763,15 @@ pub fn fd_filestat_set_size( /// - `__wasi_fstflags_t fst_flags` /// Bit-vector for controlling which times get set pub fn fd_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { debug!("wasi::fd_filestat_set_times"); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_FILESTAT_SET_TIMES) { @@ -795,7 +825,7 @@ pub fn fd_filestat_set_times( /// - `size_t nread` /// The number of bytes read pub fn fd_pread( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, M>, iovs_len: M::Offset, @@ -803,10 +833,11 @@ pub fn fd_pread( nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_pread: fd={}, offset={}", fd, offset); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let iovs = wasi_try_mem_ok!(iovs.slice(memory, iovs_len)); - let nread_ref = nread.deref(memory); + let iovs = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); + let nread_ref = nread.deref(&ctx, memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_read = match fd { @@ -818,7 +849,7 @@ pub fn fd_pread( env ); if let Some(ref mut stdin) = guard.deref_mut() { - wasi_try_ok!(read_bytes(stdin, memory, iovs), env) + wasi_try_ok!(read_bytes(&ctx, stdin, memory, iovs), env) } else { return Ok(__WASI_EBADF); } @@ -846,22 +877,25 @@ pub fn fd_pread( .map_err(map_io_err), env ); - wasi_try_ok!(read_bytes(h, memory, iovs), env) + wasi_try_ok!(read_bytes(&ctx, h, memory, iovs), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.recv(memory, iovs), env) + wasi_try_ok!(socket.recv(&ctx, memory, iovs), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.recv(memory, iovs), env) + wasi_try_ok!(pipe.recv(&ctx, memory, iovs), env) } Kind::EventNotifications { .. } => return Ok(__WASI_EINVAL), Kind::Dir { .. } | Kind::Root { .. } => return Ok(__WASI_EISDIR), Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pread"), Kind::Buffer { buffer } => { - wasi_try_ok!(read_bytes(&buffer[(offset as usize)..], memory, iovs), env) + wasi_try_ok!( + read_bytes(&ctx, &buffer[(offset as usize)..], memory, iovs), + env + ) } } } @@ -882,20 +916,22 @@ pub fn fd_pread( /// - `__wasi_prestat *buf` /// Where the metadata will be written pub fn fd_prestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, M>, ) -> __wasi_errno_t { trace!("wasi::fd_prestat_get: fd={}", fd); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - wasi_try_mem!(buf.write(memory, wasi_try!(state.fs.prestat_fd(inodes.deref(), fd)))); + let prestat_ptr = buf.deref(&ctx, memory); + wasi_try_mem!(prestat_ptr.write(wasi_try!(state.fs.prestat_fd(inodes.deref(), fd)))); __WASI_ESUCCESS } pub fn fd_prestat_dir_name( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, @@ -905,8 +941,9 @@ pub fn fd_prestat_dir_name( fd, path_len ); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let path_chars = wasi_try_mem!(path.slice(memory, path_len)); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let path_chars = wasi_try_mem!(path.slice(&ctx, memory, path_len)); let real_inode = wasi_try!(state.fs.get_fd_inode(fd)); let inode_val = &inodes.arena[real_inode]; @@ -956,7 +993,7 @@ pub fn fd_prestat_dir_name( /// - `u32 *nwritten` /// Number of bytes written pub fn fd_pwrite( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, M>, iovs_len: M::Offset, @@ -965,9 +1002,10 @@ pub fn fd_pwrite( ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_pwrite"); // TODO: refactor, this is just copied from `fd_write`... - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let iovs_arr = wasi_try_mem_ok!(iovs.slice(memory, iovs_len)); - let nwritten_ref = nwritten.deref(memory); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let iovs_arr = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); + let nwritten_ref = nwritten.deref(&ctx, memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_written = match fd { @@ -980,7 +1018,7 @@ pub fn fd_pwrite( env ); if let Some(ref mut stdout) = guard.deref_mut() { - wasi_try_ok!(write_bytes(stdout, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(&ctx, stdout, memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -993,7 +1031,7 @@ pub fn fd_pwrite( env ); if let Some(ref mut stderr) = guard.deref_mut() { - wasi_try_ok!(write_bytes(stderr, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(&ctx, stderr, memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1018,16 +1056,16 @@ pub fn fd_pwrite( .map_err(map_io_err), env ); - wasi_try_ok!(write_bytes(handle, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(&ctx, handle, memory, iovs_arr), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.send(memory, iovs_arr), env) + wasi_try_ok!(socket.send(&ctx, memory, iovs_arr), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.send(memory, iovs_arr), env) + wasi_try_ok!(pipe.send(&ctx, memory, iovs_arr), env) } Kind::Dir { .. } | Kind::Root { .. } => { // TODO: verify @@ -1037,7 +1075,7 @@ pub fn fd_pwrite( Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pwrite"), Kind::Buffer { buffer } => { wasi_try_ok!( - write_bytes(&mut buffer[(offset as usize)..], memory, iovs_arr), + write_bytes(&ctx, &mut buffer[(offset as usize)..], memory, iovs_arr), env ) } @@ -1066,17 +1104,18 @@ pub fn fd_pwrite( /// Number of bytes read /// pub fn fd_read( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, M>, iovs_len: M::Offset, nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_read: fd={}", fd); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let iovs_arr = wasi_try_mem_ok!(iovs.slice(memory, iovs_len)); - let nread_ref = nread.deref(memory); + let iovs_arr = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); + let nread_ref = nread.deref(&ctx, memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_read = match fd { @@ -1088,7 +1127,7 @@ pub fn fd_read( env ); if let Some(ref mut stdin) = guard.deref_mut() { - wasi_try_ok!(read_bytes(stdin, memory, iovs_arr), env) + wasi_try_ok!(read_bytes(&ctx, stdin, memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1116,16 +1155,16 @@ pub fn fd_read( .map_err(map_io_err), env ); - wasi_try_ok!(read_bytes(handle, memory, iovs_arr), env) + wasi_try_ok!(read_bytes(&ctx, handle, memory, iovs_arr), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.recv(memory, iovs_arr), env) + wasi_try_ok!(socket.recv(&ctx, memory, iovs_arr), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.recv(memory, iovs_arr), env) + wasi_try_ok!(pipe.recv(&ctx, memory, iovs_arr), env) } Kind::Dir { .. } | Kind::Root { .. } => { // TODO: verify @@ -1164,7 +1203,7 @@ pub fn fd_read( { let reader = val.to_ne_bytes(); ret = wasi_try_ok!( - read_bytes(&reader[..], memory, iovs_arr), + read_bytes(&ctx, &reader[..], memory, iovs_arr), env ); break; @@ -1188,7 +1227,7 @@ pub fn fd_read( } Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"), Kind::Buffer { buffer } => { - wasi_try_ok!(read_bytes(&buffer[offset..], memory, iovs_arr), env) + wasi_try_ok!(read_bytes(&ctx, &buffer[offset..], memory, iovs_arr), env) } } }; @@ -1224,7 +1263,7 @@ pub fn fd_read( /// The Number of bytes stored in `buf`; if less than `buf_len` then entire /// directory has been read pub fn fd_readdir( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr, buf_len: M::Offset, @@ -1232,12 +1271,13 @@ pub fn fd_readdir( bufused: WasmPtr, ) -> __wasi_errno_t { trace!("wasi::fd_readdir"); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); // TODO: figure out how this is supposed to work; // is it supposed to pack the buffer full every time until it can't? or do one at a time? - let buf_arr = wasi_try_mem!(buf.slice(memory, buf_len)); - let bufused_ref = bufused.deref(memory); + let buf_arr = wasi_try_mem!(buf.slice(&ctx, memory, buf_len)); + let bufused_ref = bufused.deref(&ctx, memory); let working_dir = wasi_try!(state.fs.get_fd(fd)); let mut cur_cookie = cookie; let mut buf_idx = 0usize; @@ -1351,9 +1391,14 @@ pub fn fd_readdir( /// File descriptor to copy /// - `__wasi_fd_t to` /// Location to copy file descriptor to -pub fn fd_renumber(env: &WasiEnv, from: __wasi_fd_t, to: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_renumber( + ctx: ContextMut<'_, WasiEnv>, + from: __wasi_fd_t, + to: __wasi_fd_t, +) -> __wasi_errno_t { debug!("wasi::fd_renumber: from={}, to={}", from, to); - let (_, state) = env.get_memory_and_wasi_state(0); + let env = ctx.data(); + let (_, mut state) = env.get_memory_and_wasi_state(0); let mut fd_map = state.fs.fd_map.write().unwrap(); let fd_entry = wasi_try!(fd_map.get_mut(&from).ok_or(__WASI_EBADF)); @@ -1378,16 +1423,17 @@ pub fn fd_renumber(env: &WasiEnv, from: __wasi_fd_t, to: __wasi_fd_t) -> __wasi_ /// - `__wasi_fd_t fd` /// The new file handle that is a duplicate of the original pub fn fd_dup( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, ret_fd: WasmPtr<__wasi_fd_t, M>, ) -> __wasi_errno_t { debug!("wasi::fd_dup"); + let env = ctx.data(); let (memory, state) = env.get_memory_and_wasi_state(0); let fd = wasi_try!(state.fs.clone_fd(fd)); - wasi_try_mem!(ret_fd.write(memory, fd)); + wasi_try_mem!(ret_fd.write(&ctx, memory, fd)); __WASI_ESUCCESS } @@ -1395,13 +1441,14 @@ pub fn fd_dup( /// ### `fd_event()` /// Creates a file handle for event notifications pub fn fd_event( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, initial_val: u64, flags: __wasi_eventfdflags, ret_fd: WasmPtr<__wasi_fd_t, M>, ) -> __wasi_errno_t { debug!("wasi::fd_event"); + let env = ctx.data(); let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let kind = Kind::EventNotifications { @@ -1419,7 +1466,7 @@ pub fn fd_event( let rights = __WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_POLL_FD_READWRITE; let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem!(ret_fd.write(memory, fd)); + wasi_try_mem!(ret_fd.write(&ctx, memory, fd)); __WASI_ESUCCESS } @@ -1437,15 +1484,16 @@ pub fn fd_event( /// - `__wasi_filesize_t *fd` /// The new offset relative to the start of the file pub fn fd_seek( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, newoffset: WasmPtr<__wasi_filesize_t, M>, ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_seek: fd={}, offset={}", fd, offset); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let new_offset_ref = newoffset.deref(memory); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let new_offset_ref = newoffset.deref(&ctx, memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_SEEK) { @@ -1519,10 +1567,11 @@ pub fn fd_seek( /// TODO: figure out which errors this should return /// - `__WASI_EPERM` /// - `__WASI_ENOTCAPABLE` -pub fn fd_sync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_sync"); debug!("=> fd={}", fd); - let (_, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_SYNC) { return __WASI_EACCES; @@ -1561,13 +1610,14 @@ pub fn fd_sync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { /// - `__wasi_filesize_t *offset` /// The offset of `fd` relative to the start of the file pub fn fd_tell( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, M>, ) -> __wasi_errno_t { debug!("wasi::fd_tell"); - let (memory, state) = env.get_memory_and_wasi_state(0); - let offset_ref = offset.deref(memory); + let env = ctx.data(); + let (memory, mut state) = env.get_memory_and_wasi_state(0); + let offset_ref = offset.deref(&ctx, memory); let fd_entry = wasi_try!(state.fs.get_fd(fd)); @@ -1595,16 +1645,17 @@ pub fn fd_tell( /// Errors: /// pub fn fd_write( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, M>, iovs_len: M::Offset, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::fd_write: fd={}", fd); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let iovs_arr = wasi_try_mem_ok!(iovs.slice(memory, iovs_len)); - let nwritten_ref = nwritten.deref(memory); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let iovs_arr = wasi_try_mem_ok!(iovs.slice(&ctx, memory, iovs_len)); + let nwritten_ref = nwritten.deref(&ctx, memory); let fd_entry = wasi_try_ok!(state.fs.get_fd(fd)); let bytes_written = match fd { @@ -1617,7 +1668,7 @@ pub fn fd_write( env ); if let Some(ref mut stdout) = guard.deref_mut() { - wasi_try_ok!(write_bytes(stdout, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(&ctx, stdout, memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1630,7 +1681,7 @@ pub fn fd_write( env ); if let Some(ref mut stderr) = guard.deref_mut() { - wasi_try_ok!(write_bytes(stderr, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(&ctx, stderr, memory, iovs_arr), env) } else { return Ok(__WASI_EBADF); } @@ -1655,16 +1706,16 @@ pub fn fd_write( .map_err(map_io_err), env ); - wasi_try_ok!(write_bytes(handle, memory, iovs_arr), env) + wasi_try_ok!(write_bytes(&ctx, handle, memory, iovs_arr), env) } else { return Ok(__WASI_EINVAL); } } Kind::Socket { socket } => { - wasi_try_ok!(socket.send(memory, iovs_arr), env) + wasi_try_ok!(socket.send(&ctx, memory, iovs_arr), env) } Kind::Pipe { pipe } => { - wasi_try_ok!(pipe.send(memory, iovs_arr), env) + wasi_try_ok!(pipe.send(&ctx, memory, iovs_arr), env) } Kind::Dir { .. } | Kind::Root { .. } => { // TODO: verify @@ -1674,7 +1725,8 @@ pub fn fd_write( counter, wakers, .. } => { let mut val = 0u64.to_ne_bytes(); - let written = wasi_try_ok!(write_bytes(&mut val[..], memory, iovs_arr)); + let written = + wasi_try_ok!(write_bytes(&ctx, &mut val[..], memory, iovs_arr)); if written != val.len() { return Ok(__WASI_EINVAL); } @@ -1694,7 +1746,10 @@ pub fn fd_write( } Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_write"), Kind::Buffer { buffer } => { - wasi_try_ok!(write_bytes(&mut buffer[offset..], memory, iovs_arr), env) + wasi_try_ok!( + write_bytes(&ctx, &mut buffer[offset..], memory, iovs_arr), + env + ) } } }; @@ -1726,12 +1781,13 @@ pub fn fd_write( /// - `__wasi_fd_t` /// Second file handle that represents the other end of the pipe pub fn fd_pipe( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ro_fd1: WasmPtr<__wasi_fd_t, M>, ro_fd2: WasmPtr<__wasi_fd_t, M>, ) -> __wasi_errno_t { trace!("wasi::fd_pipe"); + let env = ctx.data(); let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let (pipe1, pipe2) = WasiPipe::new(); @@ -1753,8 +1809,8 @@ pub fn fd_pipe( let fd1 = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode1)); let fd2 = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode2)); - wasi_try_mem!(ro_fd1.write(memory, fd1)); - wasi_try_mem!(ro_fd2.write(memory, fd2)); + wasi_try_mem!(ro_fd1.write(&ctx, memory, fd1)); + wasi_try_mem!(ro_fd2.write(&ctx, memory, fd2)); __WASI_ESUCCESS } @@ -1773,12 +1829,13 @@ pub fn fd_pipe( /// - __WASI_RIGHT_PATH_CREATE_DIRECTORY /// This right must be set on the directory that the file is created in (TODO: verify that this is true) pub fn path_create_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, ) -> __wasi_errno_t { debug!("wasi::path_create_directory"); + let env = ctx.data(); let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let working_dir = wasi_try!(state.fs.get_fd(fd)); @@ -1791,7 +1848,7 @@ pub fn path_create_directory( if !has_rights(working_dir.rights, __WASI_RIGHT_PATH_CREATE_DIRECTORY) { return __WASI_EACCES; } - let path_string = unsafe { get_input_str!(memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; debug!("=> fd: {}, path: {}", fd, &path_string); let path = std::path::PathBuf::from(&path_string); @@ -1900,7 +1957,7 @@ pub fn path_create_directory( /// - `__wasi_file_stat_t *buf` /// The location where the metadata will be stored pub fn path_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -1908,9 +1965,10 @@ pub fn path_filestat_get( buf: WasmPtr<__wasi_filestat_t, M>, ) -> __wasi_errno_t { debug!("wasi::path_filestat_get (fd={})", fd); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); - let path_string = unsafe { get_input_str!(memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; let stat = wasi_try!(path_filestat_get_internal( memory, @@ -1921,7 +1979,7 @@ pub fn path_filestat_get( &path_string )); - wasi_try_mem!(buf.deref(memory).write(stat)); + wasi_try_mem!(buf.deref(&ctx, memory).write(stat)); __WASI_ESUCCESS } @@ -1987,7 +2045,7 @@ pub fn path_filestat_get_internal( /// - `__wasi_fstflags_t fst_flags` /// A bitmask controlling which attributes are set pub fn path_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -1997,7 +2055,8 @@ pub fn path_filestat_set_times( fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { debug!("wasi::path_filestat_set_times"); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let fd_entry = wasi_try!(state.fs.get_fd(fd)); let fd_inode = fd_entry.inode; if !has_rights(fd_entry.rights, __WASI_RIGHT_PATH_FILESTAT_SET_TIMES) { @@ -2010,7 +2069,7 @@ pub fn path_filestat_set_times( return __WASI_EINVAL; } - let path_string = unsafe { get_input_str!(memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; debug!("=> base_fd: {}, path: {}", fd, &path_string); let file_inode = wasi_try!(state.fs.get_inode_at_path( @@ -2064,7 +2123,7 @@ pub fn path_filestat_set_times( /// - `u32 old_path_len` /// Length of the `new_path` string pub fn path_link( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -2077,9 +2136,10 @@ pub fn path_link( if old_flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0 { debug!(" - will follow symlinks when opening path"); } - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); - let old_path_str = unsafe { get_input_str!(memory, old_path, old_path_len) }; - let new_path_str = unsafe { get_input_str!(memory, new_path, new_path_len) }; + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let old_path_str = unsafe { get_input_str!(&ctx, memory, old_path, old_path_len) }; + let new_path_str = unsafe { get_input_str!(&ctx, memory, new_path, new_path_len) }; let source_fd = wasi_try!(state.fs.get_fd(old_fd)); let target_fd = wasi_try!(state.fs.get_fd(new_fd)); debug!( @@ -2159,7 +2219,7 @@ pub fn path_link( /// Possible Errors: /// - `__WASI_EACCES`, `__WASI_EBADF`, `__WASI_EFAULT`, `__WASI_EFBIG?`, `__WASI_EINVAL`, `__WASI_EIO`, `__WASI_ELOOP`, `__WASI_EMFILE`, `__WASI_ENAMETOOLONG?`, `__WASI_ENFILE`, `__WASI_ENOENT`, `__WASI_ENOTDIR`, `__WASI_EROFS`, and `__WASI_ENOTCAPABLE` pub fn path_open( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -2174,14 +2234,15 @@ pub fn path_open( if dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0 { debug!(" - will follow symlinks when opening path"); } - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); /* TODO: find actual upper bound on name size (also this is a path, not a name :think-fish:) */ let path_len64: u64 = path_len.into(); if path_len64 > 1024u64 * 1024u64 { return __WASI_ENAMETOOLONG; } - let fd_ref = fd.deref(memory); + let fd_ref = fd.deref(&ctx, memory); // o_flags: // - __WASI_O_CREAT (create if it does not exist) @@ -2196,7 +2257,7 @@ pub fn path_open( if !has_rights(working_dir.rights, __WASI_RIGHT_PATH_OPEN) { return __WASI_EACCES; } - let path_string = unsafe { get_input_str!(memory, path, path_len) }; + let path_string = unsafe { get_input_str!(&ctx, memory, path, path_len) }; debug!("=> fd: {}, path: {}", dirfd, &path_string); @@ -2401,7 +2462,7 @@ pub fn path_open( /// - `u32 buf_used` /// The number of bytes written to `buf` pub fn path_readlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, @@ -2410,13 +2471,14 @@ pub fn path_readlink( buf_used: WasmPtr, ) -> __wasi_errno_t { debug!("wasi::path_readlink"); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let base_dir = wasi_try!(state.fs.get_fd(dir_fd)); if !has_rights(base_dir.rights, __WASI_RIGHT_PATH_READLINK) { return __WASI_EACCES; } - let path_str = unsafe { get_input_str!(memory, path, path_len) }; + let path_str = unsafe { get_input_str!(&ctx, memory, path, path_len) }; let inode = wasi_try!(state .fs .get_inode_at_path(inodes.deref_mut(), dir_fd, &path_str, false)); @@ -2433,13 +2495,14 @@ pub fn path_readlink( } let bytes: Vec<_> = bytes.collect(); - let out = wasi_try_mem!(buf.slice(memory, wasi_try!(to_offset::(bytes.len())))); - wasi_try_mem!(out.write_slice(&bytes[..])); + let out = + wasi_try_mem!(buf.slice(&ctx, memory, wasi_try!(to_offset::(bytes.len())))); + wasi_try_mem!(out.write_slice(&bytes)); // should we null terminate this? let bytes_len: M::Offset = wasi_try!(bytes.len().try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(buf_used.deref(memory).write(bytes_len)); + wasi_try_mem!(buf_used.deref(&ctx, memory).write(bytes_len)); } else { return __WASI_EINVAL; } @@ -2450,17 +2513,18 @@ pub fn path_readlink( /// Returns __WASI_ENOTEMTPY if directory is not empty pub fn path_remove_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, ) -> __wasi_errno_t { // TODO check if fd is a dir, ensure it's within sandbox, etc. debug!("wasi::path_remove_directory"); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let base_dir = wasi_try!(state.fs.get_fd(fd)); - let path_str = unsafe { get_input_str!(memory, path, path_len) }; + let path_str = unsafe { get_input_str!(&ctx, memory, path, path_len) }; let inode = wasi_try!(state .fs @@ -2534,7 +2598,7 @@ pub fn path_remove_directory( /// - `u32 new_path_len` /// The number of bytes to read from `new_path` pub fn path_rename( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: M::Offset, @@ -2546,10 +2610,11 @@ pub fn path_rename( "wasi::path_rename: old_fd = {}, new_fd = {}", old_fd, new_fd ); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); - let source_str = unsafe { get_input_str!(memory, old_path, old_path_len) }; + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let source_str = unsafe { get_input_str!(&ctx, memory, old_path, old_path_len) }; let source_path = std::path::Path::new(&source_str); - let target_str = unsafe { get_input_str!(memory, new_path, new_path_len) }; + let target_str = unsafe { get_input_str!(&ctx, memory, new_path, new_path_len) }; let target_path = std::path::Path::new(&target_str); debug!("=> rename from {} to {}", &source_str, &target_str); @@ -2697,7 +2762,7 @@ pub fn path_rename( /// - `u32 new_path_len` /// The number of bytes to read from `new_path` pub fn path_symlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_path: WasmPtr, old_path_len: M::Offset, fd: __wasi_fd_t, @@ -2705,9 +2770,10 @@ pub fn path_symlink( new_path_len: M::Offset, ) -> __wasi_errno_t { debug!("wasi::path_symlink"); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); - let old_path_str = unsafe { get_input_str!(memory, old_path, old_path_len) }; - let new_path_str = unsafe { get_input_str!(memory, new_path, new_path_len) }; + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let old_path_str = unsafe { get_input_str!(&ctx, memory, old_path, old_path_len) }; + let new_path_str = unsafe { get_input_str!(&ctx, memory, new_path, new_path_len) }; let base_fd = wasi_try!(state.fs.get_fd(fd)); if !has_rights(base_fd.rights, __WASI_RIGHT_PATH_SYMLINK) { return __WASI_EACCES; @@ -2796,19 +2862,20 @@ pub fn path_symlink( /// - `u32 path_len` /// The number of bytes in the `path` array pub fn path_unlink_file( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, ) -> __wasi_errno_t { debug!("wasi::path_unlink_file"); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let base_dir = wasi_try!(state.fs.get_fd(fd)); if !has_rights(base_dir.rights, __WASI_RIGHT_PATH_UNLINK_FILE) { return __WASI_EACCES; } - let path_str = unsafe { get_input_str!(memory, path, path_len) }; + let path_str = unsafe { get_input_str!(&ctx, memory, path, path_len) }; debug!("Requested file: {}", path_str); let inode = wasi_try!(state @@ -2906,7 +2973,7 @@ pub fn path_unlink_file( /// - `u32 nevents` /// The number of events seen pub fn poll_oneoff( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, in_: WasmPtr<__wasi_subscription_t, M>, out_: WasmPtr<__wasi_event_t, M>, nsubscriptions: M::Offset, @@ -2914,12 +2981,13 @@ pub fn poll_oneoff( ) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::poll_oneoff"); trace!(" => nsubscriptions = {}", nsubscriptions); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); - let subscription_array = wasi_try_mem_ok!(in_.slice(memory, nsubscriptions)); - let event_array = wasi_try_mem_ok!(out_.slice(memory, nsubscriptions)); + let subscription_array = wasi_try_mem_ok!(in_.slice(&ctx, memory, nsubscriptions)); + let event_array = wasi_try_mem_ok!(out_.slice(&ctx, memory, nsubscriptions)); let mut events_seen: u32 = 0; - let out_ptr = nevents.deref(memory); + let out_ptr = nevents.deref(&ctx, memory); let mut fd_guards = vec![]; let mut clock_subs = vec![]; @@ -3155,7 +3223,7 @@ pub fn poll_oneoff( /// Inputs: /// - `__wasi_exitcode_t` /// Exit code to return to the operating system -pub fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) -> Result<(), WasiError> { +pub fn proc_exit(ctx: ContextMut<'_, WasiEnv>, code: __wasi_exitcode_t) -> Result<(), WasiError> { debug!("wasi::proc_exit, {}", code); Err(WasiError::Exit(code)) } @@ -3166,15 +3234,16 @@ pub fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) -> Result<(), WasiError /// Inputs: /// - `__wasi_signal_t` /// Signal to be raised for this process -pub fn proc_raise(env: &WasiEnv, sig: __wasi_signal_t) -> __wasi_errno_t { +pub fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { debug!("wasi::proc_raise"); unimplemented!("wasi::proc_raise") } /// ### `sched_yield()` /// Yields execution of the thread -pub fn sched_yield(env: &WasiEnv) -> Result<__wasi_errno_t, WasiError> { +pub fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::sched_yield"); + let env = ctx.data(); env.yield_now()?; Ok(__WASI_ESUCCESS) } @@ -3187,18 +3256,19 @@ pub fn sched_yield(env: &WasiEnv) -> Result<__wasi_errno_t, WasiError> { /// - `size_t buf_len` /// The number of bytes that will be written pub fn random_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, buf: WasmPtr, buf_len: M::Offset, ) -> __wasi_errno_t { trace!("wasi::random_get buf_len: {}", buf_len); + let env = ctx.data(); let memory = env.memory(); let buf_len64: u64 = buf_len.into(); let mut u8_buffer = vec![0; buf_len64 as usize]; let res = getrandom::getrandom(&mut u8_buffer); match res { Ok(()) => { - let buf = wasi_try_mem!(buf.slice(memory, buf_len)); + let buf = wasi_try_mem!(buf.slice(&ctx, memory, buf_len)); wasi_try_mem!(buf.write_slice(&u8_buffer)); __WASI_ESUCCESS } @@ -3209,10 +3279,11 @@ pub fn random_get( /// ### `tty_get()` /// Retrieves the current state of the TTY pub fn tty_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, M>, ) -> __wasi_errno_t { debug!("wasi::tty_stdin"); + let env = ctx.data(); let state = env.runtime.tty_get(); let state = __wasi_tty_t { @@ -3243,7 +3314,7 @@ pub fn tty_get( }; let memory = env.memory(); - wasi_try_mem!(tty_state.write(memory, state)); + wasi_try_mem!(tty_state.write(&ctx, memory, state)); __WASI_ESUCCESS } @@ -3251,13 +3322,14 @@ pub fn tty_get( /// ### `tty_set()` /// Updates the properties of the rect pub fn tty_set( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, M>, ) -> __wasi_errno_t { - debug!("wasi::tty_stdout"); + debug!("wasi::tty_set"); + let env = ctx.data(); let memory = env.memory(); - let state = wasi_try_mem!(tty_state.read(memory)); + let state = wasi_try_mem!(tty_state.read(&ctx, memory)); let state = super::runtime::WasiTtyState { cols: state.cols, rows: state.rows, @@ -3300,23 +3372,24 @@ pub fn tty_set( /// If the path exceeds the size of the buffer then this function /// will fill the path_len with the needed size and return EOVERFLOW pub fn getcwd( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, path: WasmPtr, path_len: WasmPtr, ) -> __wasi_errno_t { - debug!("wasi::getpwd"); - let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); + debug!("wasi::getcwd"); + let env = ctx.data(); + let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let (_, cur_dir) = wasi_try!(state .fs .get_current_dir(inodes.deref_mut(), crate::VIRTUAL_ROOT_FD,)); - let max_path_len = wasi_try_mem!(path_len.read(memory)); - let path_slice = wasi_try_mem!(path.slice(memory, max_path_len)); + let max_path_len = wasi_try_mem!(path_len.read(&ctx, memory)); + let path_slice = wasi_try_mem!(path.slice(&ctx, memory, max_path_len)); let max_path_len: u64 = max_path_len.into(); let cur_dir = cur_dir.as_bytes(); - wasi_try_mem!(path_len.write(memory, wasi_try!(to_offset::(cur_dir.len())))); + wasi_try_mem!(path_len.write(&ctx, memory, wasi_try!(to_offset::(cur_dir.len())))); if cur_dir.len() as u64 >= max_path_len { return __WASI_EOVERFLOW; } @@ -3340,14 +3413,14 @@ pub fn getcwd( /// ### `chdir()` /// Sets the current working directory pub fn chdir( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, path: WasmPtr, path_len: M::Offset, ) -> __wasi_errno_t { debug!("wasi::chdir"); - - let (memory, state) = env.get_memory_and_wasi_state(0); - let path = unsafe { get_input_str!(memory, path, path_len) }; + let env = ctx.data(); + let (memory, mut state) = env.get_memory_and_wasi_state(0); + let path = unsafe { get_input_str!(&ctx, memory, path, path_len) }; state.fs.set_current_dir(path.as_str()); __WASI_ESUCCESS @@ -3372,7 +3445,7 @@ pub fn chdir( /// Returns the thread index of the newly created thread /// (indices always start from zero) pub fn thread_spawn( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, method: WasmPtr, method_len: M::Offset, user_data: u64, @@ -3380,19 +3453,22 @@ pub fn thread_spawn( ret_tid: WasmPtr<__wasi_tid_t, M>, ) -> __wasi_errno_t { debug!("wasi::thread_spawn"); + let env = ctx.data(); let memory = env.memory(); - let method = unsafe { get_input_str!(memory, method, method_len) }; + let method = unsafe { get_input_str!(&ctx, memory, method, method_len) }; // Load the callback function if method.as_str() != "_thread_start" { return __WASI_ENOTCAPABLE; }; + /* let funct = unsafe { if env.thread_start_ref().is_none() { return __WASI_EADDRNOTAVAIL; } env.thread_start_ref_unchecked() }; + */ let reactor = match reactor { __WASI_BOOL_FALSE => false, @@ -3410,6 +3486,7 @@ pub fn thread_spawn( wasi_try!(env .runtime .thread_spawn(Box::new(move || { + /* if let Some(funct) = sub_env.thread_start_ref() { if let Err(err) = funct.call(user_data) { warn!("thread failed: {}", err); @@ -3421,6 +3498,7 @@ pub fn thread_spawn( std::mem::forget(sub_thread); return; } + */ let thread = { let mut guard = sub_env.state.threading.lock().unwrap(); @@ -3443,7 +3521,7 @@ pub fn thread_spawn( }; let child: __wasi_tid_t = child.into(); - wasi_try_mem!(ret_tid.write(memory, child)); + wasi_try_mem!(ret_tid.write(&ctx, memory, child)); __WASI_ESUCCESS } @@ -3454,11 +3532,12 @@ pub fn thread_spawn( /// /// * `duration` - Amount of time that the thread should sleep pub fn thread_sleep( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, duration: __wasi_timestamp_t, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::thread_sleep"); + let env = ctx.data(); let duration = Duration::from_nanos(duration as u64); env.sleep(duration)?; Ok(__WASI_ESUCCESS) @@ -3468,13 +3547,14 @@ pub fn thread_sleep( /// Returns the index of the current thread /// (threads indices are sequencial from zero) pub fn thread_id( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_tid: WasmPtr<__wasi_tid_t, M>, ) -> __wasi_errno_t { debug!("wasi::thread_id"); + let env = ctx.data(); let tid: __wasi_tid_t = env.id.into(); - wasi_try_mem!(ret_tid.write(env.memory(), tid)); + wasi_try_mem!(ret_tid.write(&ctx, env.memory(), tid)); __WASI_ESUCCESS } @@ -3485,9 +3565,13 @@ pub fn thread_id( /// ## Parameters /// /// * `tid` - Handle of the thread to wait on -pub fn thread_join(env: &WasiEnv, tid: __wasi_tid_t) -> Result<__wasi_errno_t, WasiError> { +pub fn thread_join( + ctx: ContextMut<'_, WasiEnv>, + tid: __wasi_tid_t, +) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::thread_join"); + let env = ctx.data(); let tid: WasiThreadId = tid.into(); let other_thread = { let guard = env.state.threading.lock().unwrap(); @@ -3510,28 +3594,33 @@ pub fn thread_join(env: &WasiEnv, tid: __wasi_tid_t) -> Result<__wasi_errno_t, W /// Returns the available parallelism which is normally the /// number of available cores that can run concurrently pub fn thread_parallelism( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_parallelism: WasmPtr, ) -> __wasi_errno_t { debug!("wasi::thread_parallelism"); + let env = ctx.data(); let parallelism = wasi_try!(env.runtime().thread_parallelism().map_err(|err| { let err: __wasi_errno_t = err.into(); err })); let parallelism: M::Offset = wasi_try!(parallelism.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(ret_parallelism.write(env.memory(), parallelism)); + wasi_try_mem!(ret_parallelism.write(&ctx, env.memory(), parallelism)); __WASI_ESUCCESS } /// ### `getpid()` /// Returns the handle of the current process -pub fn getpid(env: &WasiEnv, ret_pid: WasmPtr<__wasi_pid_t, M>) -> __wasi_errno_t { +pub fn getpid( + ctx: ContextMut<'_, WasiEnv>, + ret_pid: WasmPtr<__wasi_pid_t, M>, +) -> __wasi_errno_t { debug!("wasi::getpid"); + let env = ctx.data(); let pid = env.runtime().getpid(); if let Some(pid) = pid { - wasi_try_mem!(ret_pid.write(env.memory(), pid as __wasi_pid_t)); + wasi_try_mem!(ret_pid.write(&ctx, env.memory(), pid as __wasi_pid_t)); __WASI_ESUCCESS } else { __WASI_ENOTSUP @@ -3548,7 +3637,7 @@ pub fn getpid(env: &WasiEnv, ret_pid: WasmPtr<__wasi_pid_t, M>) - /// /// * `rval` - The exit code returned by the process. pub fn thread_exit( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, exitcode: __wasi_exitcode_t, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::thread_exit"); @@ -3575,7 +3664,7 @@ pub fn thread_exit( /// /// Returns a bus process id that can be used to invoke calls pub fn process_spawn( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, chroot: __wasi_bool_t, @@ -3590,12 +3679,13 @@ pub fn process_spawn( working_dir_len: M::Offset, ret_handles: WasmPtr<__wasi_bus_handles_t, M>, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory(); - let name = unsafe { get_input_str_bus!(memory, name, name_len) }; - let args = unsafe { get_input_str_bus!(memory, args, args_len) }; - let preopen = unsafe { get_input_str_bus!(memory, preopen, preopen_len) }; - let working_dir = unsafe { get_input_str_bus!(memory, working_dir, working_dir_len) }; + let name = unsafe { get_input_str_bus!(&ctx, memory, name, name_len) }; + let args = unsafe { get_input_str_bus!(&ctx, memory, args, args_len) }; + let preopen = unsafe { get_input_str_bus!(&ctx, memory, preopen, preopen_len) }; + let working_dir = unsafe { get_input_str_bus!(&ctx, memory, working_dir, working_dir_len) }; let chroot = chroot == __WASI_BOOL_TRUE; debug!("wasi::process_spawn (name={})", name); @@ -3657,7 +3747,7 @@ pub fn process_spawn( stderr, }; - wasi_try_mem_bus!(ret_handles.write(memory, handles)); + wasi_try_mem_bus!(ret_handles.write(&ctx, memory, handles)); __BUS_ESUCCESS } @@ -3675,19 +3765,20 @@ pub fn process_spawn( /// /// Returns a bus process id that can be used to invoke calls pub fn bus_open_local( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, reuse: __wasi_bool_t, ret_bid: WasmPtr<__wasi_bid_t, M>, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory(); - let name = unsafe { get_input_str_bus!(memory, name, name_len) }; + let name = unsafe { get_input_str_bus!(&ctx, memory, name, name_len) }; let reuse = reuse == __WASI_BOOL_TRUE; debug!("wasi::bus_open_local (name={}, reuse={})", name, reuse); - bus_open_local_internal(env, name, reuse, None, None, ret_bid) + bus_open_local_internal(ctx, name, reuse, None, None, ret_bid) } /// Spawns a new bus process for a particular web WebAssembly @@ -3705,7 +3796,7 @@ pub fn bus_open_local( /// /// Returns a bus process id that can be used to invoke calls pub fn bus_open_remote( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, reuse: __wasi_bool_t, @@ -3715,28 +3806,30 @@ pub fn bus_open_remote( token_len: M::Offset, ret_bid: WasmPtr<__wasi_bid_t, M>, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory(); - let name = unsafe { get_input_str_bus!(memory, name, name_len) }; - let instance = unsafe { get_input_str_bus!(memory, instance, instance_len) }; - let token = unsafe { get_input_str_bus!(memory, token, token_len) }; + let name = unsafe { get_input_str_bus!(&ctx, memory, name, name_len) }; + let instance = unsafe { get_input_str_bus!(&ctx, memory, instance, instance_len) }; + let token = unsafe { get_input_str_bus!(&ctx, memory, token, token_len) }; let reuse = reuse == __WASI_BOOL_TRUE; debug!( "wasi::bus_open_remote (name={}, reuse={}, instance={})", name, reuse, instance ); - bus_open_local_internal(env, name, reuse, Some(instance), Some(token), ret_bid) + bus_open_local_internal(ctx, name, reuse, Some(instance), Some(token), ret_bid) } fn bus_open_local_internal( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: String, reuse: bool, instance: Option, token: Option, ret_bid: WasmPtr<__wasi_bid_t, M>, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory(); let name: Cow<'static, str> = name.into(); @@ -3746,7 +3839,7 @@ fn bus_open_local_internal( let guard = env.state.threading.lock().unwrap(); if let Some(bid) = guard.process_reuse.get(&name) { if guard.processes.contains_key(bid) { - wasi_try_mem_bus!(ret_bid.write(memory, (*bid).into())); + wasi_try_mem_bus!(ret_bid.write(&ctx, memory, (*bid).into())); return __BUS_ESUCCESS; } } @@ -3781,7 +3874,7 @@ fn bus_open_local_internal( bid }; - wasi_try_mem_bus!(ret_bid.write(memory, bid.into())); + wasi_try_mem_bus!(ret_bid.write(&ctx, memory, bid.into())); __BUS_ESUCCESS } @@ -3791,10 +3884,11 @@ fn bus_open_local_internal( /// ## Parameters /// /// * `bid` - Handle of the bus process handle to be closed -pub fn bus_close(env: &WasiEnv, bid: __wasi_bid_t) -> __bus_errno_t { +pub fn bus_close(ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { trace!("wasi::bus_close (bid={})", bid); let bid: WasiBusProcessId = bid.into(); + let env = ctx.data(); let mut guard = env.state.threading.lock().unwrap(); guard.processes.remove(&bid); @@ -3813,7 +3907,7 @@ pub fn bus_close(env: &WasiEnv, bid: __wasi_bid_t) -> __bus_errno_t { /// * `format` - Format of the data pushed onto the bus /// * `buf` - The buffer where data to be transmitted is stored pub fn bus_call( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -3823,9 +3917,10 @@ pub fn bus_call( buf_len: M::Offset, ret_cid: WasmPtr<__wasi_cid_t, M>, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory(); - let topic = unsafe { get_input_str_bus!(memory, topic, topic_len) }; + let topic = unsafe { get_input_str_bus!(&ctx, memory, topic, topic_len) }; let keep_alive = keep_alive == __WASI_BOOL_TRUE; trace!( "wasi::bus_call (bid={}, topic={}, buf_len={})", @@ -3849,7 +3944,7 @@ pub fn bus_call( /// * `format` - Format of the data pushed onto the bus /// * `buf` - The buffer where data to be transmitted is stored pub fn bus_subcall( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, parent: __wasi_cid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -3859,9 +3954,10 @@ pub fn bus_subcall( buf_len: M::Offset, ret_cid: WasmPtr<__wasi_cid_t, M>, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory(); - let topic = unsafe { get_input_str_bus!(memory, topic, topic_len) }; + let topic = unsafe { get_input_str_bus!(&ctx, memory, topic, topic_len) }; let keep_alive = keep_alive == __WASI_BOOL_TRUE; trace!( "wasi::bus_subcall (parent={}, topic={}, buf_len={})", @@ -3888,7 +3984,7 @@ pub fn bus_subcall( /// /// Returns the number of events that have occured pub fn bus_poll( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, timeout: __wasi_timestamp_t, events: WasmPtr, nevents: M::Offset, @@ -3896,9 +3992,10 @@ pub fn bus_poll( malloc_len: M::Offset, ret_nevents: WasmPtr, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); let memory = env.memory(); - let malloc = unsafe { get_input_str_bus!(memory, malloc, malloc_len) }; + let malloc = unsafe { get_input_str_bus!(&ctx, memory, malloc, malloc_len) }; trace!("wasi::bus_poll (timeout={}, malloc={})", timeout, malloc); __BUS_EUNSUPPORTED @@ -3915,12 +4012,13 @@ pub fn bus_poll( /// * `format` - Format of the data pushed onto the bus /// * `buf` - The buffer where data to be transmitted is stored pub fn call_reply( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t, format: __wasi_busdataformat_t, buf: WasmPtr, buf_len: M::Offset, ) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); trace!( "wasi::call_reply (cid={}, format={}, data_len={})", @@ -3940,7 +4038,12 @@ pub fn call_reply( /// /// * `cid` - Handle of the call to raise a fault on /// * `fault` - Fault to be raised on the bus -pub fn call_fault(env: &WasiEnv, cid: __wasi_cid_t, fault: __bus_errno_t) -> __bus_errno_t { +pub fn call_fault( + ctx: ContextMut<'_, WasiEnv>, + cid: __wasi_cid_t, + fault: __bus_errno_t, +) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); debug!("wasi::call_fault (cid={}, fault={})", cid, fault); @@ -3952,7 +4055,8 @@ pub fn call_fault(env: &WasiEnv, cid: __wasi_cid_t, fault: __bus_errno_t) -> __b /// ## Parameters /// /// * `cid` - Handle of the bus call handle to be dropped -pub fn call_close(env: &WasiEnv, cid: __wasi_cid_t) -> __bus_errno_t { +pub fn call_close(ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { + let env = ctx.data(); let bus = env.runtime.bus(); trace!("wasi::call_close (cid={})", cid); @@ -3970,14 +4074,15 @@ pub fn call_close(env: &WasiEnv, cid: __wasi_cid_t) -> __bus_errno_t { /// /// Returns a socket handle which is used to send and receive data pub fn ws_connect( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, url: WasmPtr, url_len: M::Offset, ret_sock: WasmPtr<__wasi_fd_t, M>, ) -> __wasi_errno_t { debug!("wasi::ws_connect"); + let env = ctx.data(); let memory = env.memory(); - let url = unsafe { get_input_str!(memory, url, url_len) }; + let url = unsafe { get_input_str!(&ctx, memory, url, url_len) }; let socket = wasi_try!(env .net() @@ -3999,7 +4104,7 @@ pub fn ws_connect( let rights = super::state::all_socket_rights(); let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem!(ret_sock.write(memory, fd)); + wasi_try_mem!(ret_sock.write(&ctx, memory, fd)); __WASI_ESUCCESS } @@ -4021,7 +4126,7 @@ pub fn ws_connect( /// The body of the response can be streamed from the returned /// file handle pub fn http_request( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, url: WasmPtr, url_len: M::Offset, method: WasmPtr, @@ -4032,10 +4137,11 @@ pub fn http_request( ret_handles: WasmPtr<__wasi_http_handles_t, M>, ) -> __wasi_errno_t { debug!("wasi::http_request"); + let env = ctx.data(); let memory = env.memory(); - let url = unsafe { get_input_str!(memory, url, url_len) }; - let method = unsafe { get_input_str!(memory, method, method_len) }; - let headers = unsafe { get_input_str!(memory, headers, headers_len) }; + let url = unsafe { get_input_str!(&ctx, memory, url, url_len) }; + let method = unsafe { get_input_str!(&ctx, memory, method, method_len) }; + let headers = unsafe { get_input_str!(&ctx, memory, headers, headers_len) }; let gzip = match gzip { __WASI_BOOL_FALSE => false, @@ -4113,7 +4219,7 @@ pub fn http_request( hdr: wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode_hdr)), }; - wasi_try_mem!(ret_handles.write(memory, handles)); + wasi_try_mem!(ret_handles.write(&ctx, memory, handles)); __WASI_ESUCCESS } @@ -4127,16 +4233,17 @@ pub fn http_request( /// * `status` - Pointer to a buffer that will be filled with the current /// status of this HTTP request pub fn http_status( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, status: WasmPtr<__wasi_http_status_t, M>, ) -> __wasi_errno_t { debug!("wasi::http_status"); + let env = ctx.data(); let memory = env.memory(); - let ref_status = status.deref(memory); + let ref_status = status.deref(&ctx, memory); - let http_status = wasi_try!(__sock_actor(env, sock, 0, |socket| { + let http_status = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { socket.http_status() })); @@ -4165,7 +4272,7 @@ pub fn http_status( /// * `token` - Access token used to authenticate with the network /// * `security` - Level of encryption to encapsulate the network connection with pub fn port_bridge( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, network: WasmPtr, network_len: M::Offset, token: WasmPtr, @@ -4173,9 +4280,10 @@ pub fn port_bridge( security: __wasi_streamsecurity_t, ) -> __wasi_errno_t { debug!("wasi::port_bridge"); + let env = ctx.data(); let memory = env.memory(); - let network = unsafe { get_input_str!(memory, network, network_len) }; - let token = unsafe { get_input_str!(memory, token, token_len) }; + let network = unsafe { get_input_str!(&ctx, memory, network, network_len) }; + let token = unsafe { get_input_str!(&ctx, memory, token, token_len) }; let security = match security { __WASI_STREAM_SECURITY_UNENCRYPTED => StreamSecurity::Unencrypted, __WASI_STREAM_SECURITY_ANY_ENCRYPTION => StreamSecurity::AnyEncyption, @@ -4193,16 +4301,18 @@ pub fn port_bridge( /// ### `port_unbridge()` /// Disconnects from a remote network -pub fn port_unbridge(env: &WasiEnv) -> __wasi_errno_t { +pub fn port_unbridge(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_unbridge"); + let env = ctx.data(); wasi_try!(env.net().unbridge().map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } /// ### `port_dhcp_acquire()` /// Acquires a set of IP addresses using DHCP -pub fn port_dhcp_acquire(env: &WasiEnv) -> __wasi_errno_t { +pub fn port_dhcp_acquire(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_dhcp_acquire"); + let env = ctx.data(); wasi_try!(env.net().dhcp_acquire().map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } @@ -4214,12 +4324,13 @@ pub fn port_dhcp_acquire(env: &WasiEnv) -> __wasi_errno_t { /// /// * `addr` - Address to be added pub fn port_addr_add( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_cidr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_addr_add"); + let env = ctx.data(); let memory = env.memory(); - let cidr = wasi_try!(super::state::read_cidr(memory, ip)); + let cidr = wasi_try!(super::state::read_cidr(&ctx, memory, ip)); wasi_try!(env .net() .ip_add(cidr.ip, cidr.prefix) @@ -4234,20 +4345,22 @@ pub fn port_addr_add( /// /// * `addr` - Address to be removed pub fn port_addr_remove( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_addr_remove"); + let env = ctx.data(); let memory = env.memory(); - let ip = wasi_try!(super::state::read_ip(memory, ip)); + let ip = wasi_try!(super::state::read_ip(&ctx, memory, ip)); wasi_try!(env.net().ip_remove(ip).map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } /// ### `port_addr_clear()` /// Clears all the addresses on the local port -pub fn port_addr_clear(env: &WasiEnv) -> __wasi_errno_t { +pub fn port_addr_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_addr_clear"); + let env = ctx.data(); wasi_try!(env.net().ip_clear().map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } @@ -4255,14 +4368,15 @@ pub fn port_addr_clear(env: &WasiEnv) -> __wasi_errno_t { /// ### `port_mac()` /// Returns the MAC address of the local port pub fn port_mac( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_mac: WasmPtr<__wasi_hardwareaddress_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_mac"); + let env = ctx.data(); let memory = env.memory(); let mac = wasi_try!(env.net().mac().map_err(net_error_into_wasi_err)); let mac = __wasi_hardwareaddress_t { octs: mac }; - wasi_try_mem!(ret_mac.write(memory, mac)); + wasi_try_mem!(ret_mac.write(&ctx, memory, mac)); __WASI_ESUCCESS } @@ -4280,28 +4394,29 @@ pub fn port_mac( /// /// The number of addresses returned. pub fn port_addr_list( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, addrs: WasmPtr<__wasi_cidr_t, M>, naddrs: WasmPtr, ) -> __wasi_errno_t { debug!("wasi::port_addr_list"); + let env = ctx.data(); let memory = env.memory(); - let max_addrs = wasi_try_mem!(naddrs.read(memory)); + let max_addrs = wasi_try_mem!(naddrs.read(&ctx, memory)); let max_addrs: u64 = wasi_try!(max_addrs.try_into().map_err(|_| __WASI_EOVERFLOW)); let ref_addrs = - wasi_try_mem!(addrs.slice(memory, wasi_try!(to_offset::(max_addrs as usize)))); + wasi_try_mem!(addrs.slice(&ctx, memory, wasi_try!(to_offset::(max_addrs as usize)))); let addrs = wasi_try!(env.net().ip_list().map_err(net_error_into_wasi_err)); let addrs_len: M::Offset = wasi_try!(addrs.len().try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(naddrs.write(memory, addrs_len)); + wasi_try_mem!(naddrs.write(&ctx, memory, addrs_len)); if addrs.len() as u64 > max_addrs { return __WASI_EOVERFLOW; } for n in 0..addrs.len() { let nip = ref_addrs.index(n as u64); - super::state::write_cidr(memory, nip.as_ptr::(), *addrs.get(n).unwrap()); + super::state::write_cidr(&ctx, memory, nip.as_ptr::(), *addrs.get(n).unwrap()); } __WASI_ESUCCESS @@ -4314,12 +4429,13 @@ pub fn port_addr_list( /// /// * `addr` - Address of the default gateway pub fn port_gateway_set( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_gateway_set"); + let env = ctx.data(); let memory = env.memory(); - let ip = wasi_try!(super::state::read_ip(memory, ip)); + let ip = wasi_try!(super::state::read_ip(&ctx, memory, ip)); wasi_try!(env.net().gateway_set(ip).map_err(net_error_into_wasi_err)); __WASI_ESUCCESS @@ -4328,23 +4444,24 @@ pub fn port_gateway_set( /// ### `port_route_add()` /// Adds a new route to the local port pub fn port_route_add( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, cidr: WasmPtr<__wasi_cidr_t, M>, via_router: WasmPtr<__wasi_addr_t, M>, preferred_until: WasmPtr<__wasi_option_timestamp_t, M>, expires_at: WasmPtr<__wasi_option_timestamp_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_route_add"); + let env = ctx.data(); let memory = env.memory(); - let cidr = wasi_try!(super::state::read_cidr(memory, cidr)); - let via_router = wasi_try!(super::state::read_ip(memory, via_router)); - let preferred_until = wasi_try_mem!(preferred_until.read(memory)); + let cidr = wasi_try!(super::state::read_cidr(&ctx, memory, cidr)); + let via_router = wasi_try!(super::state::read_ip(&ctx, memory, via_router)); + let preferred_until = wasi_try_mem!(preferred_until.read(&ctx, memory)); let preferred_until = match preferred_until.tag { __WASI_OPTION_NONE => None, __WASI_OPTION_SOME => Some(Duration::from_nanos(preferred_until.u)), _ => return __WASI_EINVAL, }; - let expires_at = wasi_try_mem!(expires_at.read(memory)); + let expires_at = wasi_try_mem!(expires_at.read(&ctx, memory)); let expires_at = match expires_at.tag { __WASI_OPTION_NONE => None, __WASI_OPTION_SOME => Some(Duration::from_nanos(expires_at.u)), @@ -4361,20 +4478,22 @@ pub fn port_route_add( /// ### `port_route_remove()` /// Removes an existing route from the local port pub fn port_route_remove( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_route_remove"); + let env = ctx.data(); let memory = env.memory(); - let ip = wasi_try!(super::state::read_ip(memory, ip)); + let ip = wasi_try!(super::state::read_ip(&ctx, memory, ip)); wasi_try!(env.net().route_remove(ip).map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } /// ### `port_route_clear()` /// Clears all the routes in the local port -pub fn port_route_clear(env: &WasiEnv) -> __wasi_errno_t { +pub fn port_route_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_route_clear"); + let env = ctx.data(); wasi_try!(env.net().route_clear().map_err(net_error_into_wasi_err)); __WASI_ESUCCESS } @@ -4389,17 +4508,19 @@ pub fn port_route_clear(env: &WasiEnv) -> __wasi_errno_t { /// /// * `routes` - The buffer where routes will be stored pub fn port_route_list( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, routes: WasmPtr<__wasi_route_t, M>, nroutes: WasmPtr, ) -> __wasi_errno_t { debug!("wasi::port_route_list"); + let env = ctx.data(); let memory = env.memory(); - let nroutes = nroutes.deref(memory); + let nroutes = nroutes.deref(&ctx, memory); let max_routes: usize = wasi_try!(wasi_try_mem!(nroutes.read()) .try_into() .map_err(|_| __WASI_EINVAL)); - let ref_routes = wasi_try_mem!(routes.slice(memory, wasi_try!(to_offset::(max_routes)))); + let ref_routes = + wasi_try_mem!(routes.slice(&ctx, memory, wasi_try!(to_offset::(max_routes)))); let routes = wasi_try!(env.net().route_list().map_err(net_error_into_wasi_err)); @@ -4411,7 +4532,12 @@ pub fn port_route_list( for n in 0..routes.len() { let nroute = ref_routes.index(n as u64); - super::state::write_route(memory, nroute.as_ptr::(), routes.get(n).unwrap().clone()); + super::state::write_route( + &ctx, + memory, + nroute.as_ptr::(), + routes.get(n).unwrap().clone(), + ); } __WASI_ESUCCESS @@ -4424,7 +4550,11 @@ pub fn port_route_list( /// ## Parameters /// /// * `how` - Which channels on the socket to shut down. -pub fn sock_shutdown(env: &WasiEnv, sock: __wasi_fd_t, how: __wasi_sdflags_t) -> __wasi_errno_t { +pub fn sock_shutdown( + ctx: ContextMut<'_, WasiEnv>, + sock: __wasi_fd_t, + how: __wasi_sdflags_t, +) -> __wasi_errno_t { debug!("wasi::sock_shutdown"); let both = __WASI_SHUT_RD | __WASI_SHUT_WR; @@ -4436,7 +4566,7 @@ pub fn sock_shutdown(env: &WasiEnv, sock: __wasi_fd_t, how: __wasi_sdflags_t) -> }; wasi_try!(__sock_actor_mut( - env, + &ctx, sock, __WASI_RIGHT_SOCK_SHUTDOWN, |socket| { socket.shutdown(how) } @@ -4448,13 +4578,13 @@ pub fn sock_shutdown(env: &WasiEnv, sock: __wasi_fd_t, how: __wasi_sdflags_t) -> /// ### `sock_status()` /// Returns the current status of a socket pub fn sock_status( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_status: WasmPtr<__wasi_sockstatus_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_status"); - let status = wasi_try!(__sock_actor(env, sock, 0, |socket| { socket.status() })); + let status = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { socket.status() })); use super::state::WasiSocketStatus; let status = match status { @@ -4464,7 +4594,8 @@ pub fn sock_status( WasiSocketStatus::Failed => __WASI_SOCK_STATUS_FAILED, }; - wasi_try_mem!(ret_status.write(env.memory(), status)); + let env = ctx.data(); + wasi_try_mem!(ret_status.write(&ctx, env.memory(), status)); __WASI_ESUCCESS } @@ -4481,15 +4612,19 @@ pub fn sock_status( /// /// * `fd` - Socket that the address is bound to pub fn sock_addr_local( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_addr_local"); - let addr = wasi_try!(__sock_actor(env, sock, 0, |socket| { socket.addr_local() })); + let addr = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { + socket.addr_local() + })); + let memory = ctx.data().memory(); wasi_try!(super::state::write_ip_port( - env.memory(), + &ctx, + memory, ret_addr, addr.ip(), addr.port() @@ -4509,14 +4644,16 @@ pub fn sock_addr_local( /// /// * `fd` - Socket that the address is bound to pub fn sock_addr_peer( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ro_addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_addr_peer"); - let addr = wasi_try!(__sock_actor(env, sock, 0, |socket| { socket.addr_peer() })); + let env = ctx.data(); + let addr = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { socket.addr_peer() })); wasi_try!(super::state::write_ip_port( + &ctx, env.memory(), ro_addr, addr.ip(), @@ -4545,7 +4682,7 @@ pub fn sock_addr_peer( /// /// The file descriptor of the socket that has been opened. pub fn sock_open( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, af: __wasi_addressfamily_t, ty: __wasi_socktype_t, pt: __wasi_sockproto_t, @@ -4553,6 +4690,7 @@ pub fn sock_open( ) -> __wasi_errno_t { debug!("wasi::sock_open"); + let env = ctx.data(); let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(0); let kind = match ty { @@ -4585,7 +4723,7 @@ pub fn sock_open( let rights = super::state::all_socket_rights(); let fd = wasi_try!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem!(ro_sock.write(memory, fd)); + wasi_try_mem!(ro_sock.write(&ctx, memory, fd)); __WASI_ESUCCESS } @@ -4600,7 +4738,7 @@ pub fn sock_open( /// * `sockopt` - Socket option to be set /// * `flag` - Value to set the option to pub fn sock_set_opt_flag( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, flag: __wasi_bool_t, @@ -4614,7 +4752,7 @@ pub fn sock_set_opt_flag( }; let option: super::state::WasiSocketOption = opt.into(); - wasi_try!(__sock_actor_mut(env, sock, 0, |socket| { + wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.set_opt_flag(option, flag) })); __WASI_ESUCCESS @@ -4629,16 +4767,17 @@ pub fn sock_set_opt_flag( /// * `fd` - Socket descriptor /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_flag( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_flag: WasmPtr<__wasi_bool_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_get_opt_flag(ty={})", opt); + let env = ctx.data(); let memory = env.memory(); let option: super::state::WasiSocketOption = opt.into(); - let flag = wasi_try!(__sock_actor(env, sock, 0, |socket| { + let flag = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { socket.get_opt_flag(option) })); let flag = match flag { @@ -4646,7 +4785,7 @@ pub fn sock_get_opt_flag( true => __WASI_BOOL_TRUE, }; - wasi_try_mem!(ret_flag.write(memory, flag)); + wasi_try_mem!(ret_flag.write(&ctx, memory, flag)); __WASI_ESUCCESS } @@ -4660,15 +4799,16 @@ pub fn sock_get_opt_flag( /// * `sockopt` - Socket option to be set /// * `time` - Value to set the time to pub fn sock_set_opt_time( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, time: WasmPtr<__wasi_option_timestamp_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_set_opt_time(ty={})", opt); + let env = ctx.data(); let memory = env.memory(); - let time = wasi_try_mem!(time.read(memory)); + let time = wasi_try_mem!(time.read(&ctx, memory)); let time = match time.tag { __WASI_OPTION_NONE => None, __WASI_OPTION_SOME => Some(Duration::from_nanos(time.u)), @@ -4685,7 +4825,7 @@ pub fn sock_set_opt_time( }; let option: super::state::WasiSocketOption = opt.into(); - wasi_try!(__sock_actor_mut(env, sock, 0, |socket| { + wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.set_opt_time(ty, time) })); __WASI_ESUCCESS @@ -4699,12 +4839,13 @@ pub fn sock_set_opt_time( /// * `fd` - Socket descriptor /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_time( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_time: WasmPtr<__wasi_option_timestamp_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_get_opt_time(ty={})", opt); + let env = ctx.data(); let memory = env.memory(); let ty = match opt { @@ -4716,7 +4857,9 @@ pub fn sock_get_opt_time( _ => return __WASI_EINVAL, }; - let time = wasi_try!(__sock_actor(env, sock, 0, |socket| { socket.opt_time(ty) })); + let time = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { + socket.opt_time(ty) + })); let time = match time { None => __wasi_option_timestamp_t { tag: __WASI_OPTION_NONE, @@ -4728,7 +4871,7 @@ pub fn sock_get_opt_time( }, }; - wasi_try_mem!(ret_time.write(memory, time)); + wasi_try_mem!(ret_time.write(&ctx, memory, time)); __WASI_ESUCCESS } @@ -4743,7 +4886,7 @@ pub fn sock_get_opt_time( /// * `opt` - Socket option to be set /// * `size` - Buffer size pub fn sock_set_opt_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, size: __wasi_filesize_t, @@ -4760,7 +4903,7 @@ pub fn sock_set_opt_size( }; let option: super::state::WasiSocketOption = opt.into(); - wasi_try!(__sock_actor_mut(env, sock, 0, |socket| { + wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { match opt { __WASI_SOCK_OPTION_RECV_BUF_SIZE => socket.set_recv_buf_size(size as usize), __WASI_SOCK_OPTION_SEND_BUF_SIZE => socket.set_send_buf_size(size as usize), @@ -4781,15 +4924,16 @@ pub fn sock_set_opt_size( /// * `fd` - Socket descriptor /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_size: WasmPtr<__wasi_filesize_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_get_opt_size(ty={})", opt); + let env = ctx.data(); let memory = env.memory(); - let size = wasi_try!(__sock_actor(env, sock, 0, |socket| { + let size = wasi_try!(__sock_actor(&ctx, sock, 0, |socket| { match opt { __WASI_SOCK_OPTION_RECV_BUF_SIZE => { socket.recv_buf_size().map(|a| a as __wasi_filesize_t) @@ -4804,7 +4948,7 @@ pub fn sock_get_opt_size( _ => Err(__WASI_EINVAL), } })); - wasi_try_mem!(ret_size.write(memory, size)); + wasi_try_mem!(ret_size.write(&ctx, memory, size)); __WASI_ESUCCESS } @@ -4818,17 +4962,18 @@ pub fn sock_get_opt_size( /// * `multiaddr` - Multicast group to joined /// * `interface` - Interface that will join pub fn sock_join_multicast_v4( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, M>, iface: WasmPtr<__wasi_addr_ip4_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_join_multicast_v4"); + let env = ctx.data(); let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v4(memory, multiaddr)); - let iface = wasi_try!(super::state::read_ip_v4(memory, iface)); - wasi_try!(__sock_actor_mut(env, sock, 0, |socket| { + let multiaddr = wasi_try!(super::state::read_ip_v4(&ctx, memory, multiaddr)); + let iface = wasi_try!(super::state::read_ip_v4(&ctx, memory, iface)); + wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.join_multicast_v4(multiaddr, iface) })); __WASI_ESUCCESS @@ -4843,17 +4988,18 @@ pub fn sock_join_multicast_v4( /// * `multiaddr` - Multicast group to leave /// * `interface` - Interface that will left pub fn sock_leave_multicast_v4( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, M>, iface: WasmPtr<__wasi_addr_ip4_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_leave_multicast_v4"); + let env = ctx.data(); let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v4(memory, multiaddr)); - let iface = wasi_try!(super::state::read_ip_v4(memory, iface)); - wasi_try!(__sock_actor_mut(env, sock, 0, |socket| { + let multiaddr = wasi_try!(super::state::read_ip_v4(&ctx, memory, multiaddr)); + let iface = wasi_try!(super::state::read_ip_v4(&ctx, memory, iface)); + wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.leave_multicast_v4(multiaddr, iface) })); __WASI_ESUCCESS @@ -4868,16 +5014,17 @@ pub fn sock_leave_multicast_v4( /// * `multiaddr` - Multicast group to joined /// * `interface` - Interface that will join pub fn sock_join_multicast_v6( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, M>, iface: u32, ) -> __wasi_errno_t { debug!("wasi::sock_join_multicast_v6"); + let env = ctx.data(); let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v6(memory, multiaddr)); - wasi_try!(__sock_actor_mut(env, sock, 0, |socket| { + let multiaddr = wasi_try!(super::state::read_ip_v6(&ctx, memory, multiaddr)); + wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.join_multicast_v6(multiaddr, iface) })); __WASI_ESUCCESS @@ -4892,16 +5039,17 @@ pub fn sock_join_multicast_v6( /// * `multiaddr` - Multicast group to leave /// * `interface` - Interface that will left pub fn sock_leave_multicast_v6( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, M>, iface: u32, ) -> __wasi_errno_t { debug!("wasi::sock_leave_multicast_v6"); + let env = ctx.data(); let memory = env.memory(); - let multiaddr = wasi_try!(super::state::read_ip_v6(memory, multiaddr)); - wasi_try!(__sock_actor_mut(env, sock, 0, |socket| { + let multiaddr = wasi_try!(super::state::read_ip_v6(&ctx, memory, multiaddr)); + wasi_try!(__sock_actor_mut(&ctx, sock, 0, |socket| { socket.leave_multicast_v6(multiaddr, iface) })); __WASI_ESUCCESS @@ -4916,16 +5064,17 @@ pub fn sock_leave_multicast_v6( /// * `fd` - File descriptor of the socket to be bind /// * `addr` - Address to bind the socket to pub fn sock_bind( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_bind"); - let addr = wasi_try!(super::state::read_ip_port(env.memory(), addr)); + let env = ctx.data(); + let addr = wasi_try!(super::state::read_ip_port(&ctx, env.memory(), addr)); let addr = SocketAddr::new(addr.0, addr.1); wasi_try!(__sock_upgrade( - env, + &ctx, sock, __WASI_RIGHT_SOCK_BIND, |socket| { socket.bind(env.net(), addr) } @@ -4946,15 +5095,16 @@ pub fn sock_bind( /// * `fd` - File descriptor of the socket to be bind /// * `backlog` - Maximum size of the queue for pending connections pub fn sock_listen( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, backlog: M::Offset, ) -> __wasi_errno_t { debug!("wasi::sock_listen"); + let env = ctx.data(); let backlog: usize = wasi_try!(backlog.try_into().map_err(|_| __WASI_EINVAL)); wasi_try!(__sock_upgrade( - env, + &ctx, sock, __WASI_RIGHT_SOCK_BIND, |socket| { socket.listen(env.net(), backlog) } @@ -4975,7 +5125,7 @@ pub fn sock_listen( /// /// New socket connection pub fn sock_accept( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, fd_flags: __wasi_fdflags_t, ro_fd: WasmPtr<__wasi_fd_t, M>, @@ -4983,12 +5133,13 @@ pub fn sock_accept( ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::sock_accept"); + let env = ctx.data(); let (child, addr) = { let mut ret; let (_, state) = env.get_memory_and_wasi_state(0); loop { wasi_try_ok!( - match __sock_actor(env, sock, __WASI_RIGHT_SOCK_ACCEPT, |socket| socket + match __sock_actor(&ctx, sock, __WASI_RIGHT_SOCK_ACCEPT, |socket| socket .accept_timeout(fd_flags, Duration::from_millis(5))) { Ok(a) => { @@ -5025,8 +5176,9 @@ pub fn sock_accept( let rights = super::state::all_socket_rights(); let fd = wasi_try_ok!(state.fs.create_fd(rights, rights, 0, 0, inode)); - wasi_try_mem_ok!(ro_fd.write(memory, fd)); + wasi_try_mem_ok!(ro_fd.write(&ctx, memory, fd)); wasi_try_ok!(super::state::write_ip_port( + &ctx, memory, ro_addr, addr.ip(), @@ -5049,16 +5201,17 @@ pub fn sock_accept( /// * `fd` - Socket descriptor /// * `addr` - Address of the socket to connect to pub fn sock_connect( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { debug!("wasi::sock_connect"); - let addr = wasi_try!(super::state::read_ip_port(env.memory(), addr)); + let env = ctx.data(); + let addr = wasi_try!(super::state::read_ip_port(&ctx, env.memory(), addr)); let addr = SocketAddr::new(addr.0, addr.1); wasi_try!(__sock_upgrade( - env, + &ctx, sock, __WASI_RIGHT_SOCK_CONNECT, |socket| { socket.connect(env.net(), addr) } @@ -5080,7 +5233,7 @@ pub fn sock_connect( /// /// Number of bytes stored in ri_data and message flags. pub fn sock_recv( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, M>, ri_data_len: M::Offset, @@ -5090,19 +5243,20 @@ pub fn sock_recv( ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::sock_recv"); + let env = ctx.data(); let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(ri_data.slice(memory, ri_data_len)); + let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&ctx, memory, ri_data_len)); let bytes_read = wasi_try_ok!(__sock_actor_mut( - env, + &ctx, sock, __WASI_RIGHT_SOCK_RECV, - |socket| { socket.recv(memory, iovs_arr) } + |socket| { socket.recv(&ctx, memory, iovs_arr) } )); let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ro_flags.write(memory, 0)); - wasi_try_mem_ok!(ro_data_len.write(memory, bytes_read)); + wasi_try_mem_ok!(ro_flags.write(&ctx, memory, 0)); + wasi_try_mem_ok!(ro_data_len.write(&ctx, memory, bytes_read)); Ok(__WASI_ESUCCESS) } @@ -5121,7 +5275,7 @@ pub fn sock_recv( /// /// Number of bytes stored in ri_data and message flags. pub fn sock_recv_from( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, M>, ri_data_len: M::Offset, @@ -5132,19 +5286,20 @@ pub fn sock_recv_from( ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::sock_recv_from"); + let env = ctx.data(); let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(ri_data.slice(memory, ri_data_len)); + let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&ctx, memory, ri_data_len)); let bytes_read = wasi_try_ok!(__sock_actor_mut( - env, + &ctx, sock, __WASI_RIGHT_SOCK_RECV_FROM, - |socket| { socket.recv_from(memory, iovs_arr, ro_addr) } + |socket| { socket.recv_from(&ctx, memory, iovs_arr, ro_addr) } )); let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ro_flags.write(memory, 0)); - wasi_try_mem_ok!(ro_data_len.write(memory, bytes_read)); + wasi_try_mem_ok!(ro_flags.write(&ctx, memory, 0)); + wasi_try_mem_ok!(ro_data_len.write(&ctx, memory, bytes_read)); Ok(__WASI_ESUCCESS) } @@ -5163,7 +5318,7 @@ pub fn sock_recv_from( /// /// Number of bytes transmitted. pub fn sock_send( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, M>, si_data_len: M::Offset, @@ -5171,20 +5326,21 @@ pub fn sock_send( ret_data_len: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::sock_send"); + let env = ctx.data(); let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(si_data.slice(memory, si_data_len)); + let iovs_arr = wasi_try_mem_ok!(si_data.slice(&ctx, memory, si_data_len)); let bytes_written = wasi_try_ok!(__sock_actor_mut( - env, + &ctx, sock, __WASI_RIGHT_SOCK_SEND, - |socket| { socket.send(memory, iovs_arr) } + |socket| { socket.send(&ctx, memory, iovs_arr) } )); let bytes_written: M::Offset = wasi_try_ok!(bytes_written.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ret_data_len.write(memory, bytes_written)); + wasi_try_mem_ok!(ret_data_len.write(&ctx, memory, bytes_written)); Ok(__WASI_ESUCCESS) } @@ -5204,7 +5360,7 @@ pub fn sock_send( /// /// Number of bytes transmitted. pub fn sock_send_to( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, M>, si_data_len: M::Offset, @@ -5213,20 +5369,21 @@ pub fn sock_send_to( ret_data_len: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::sock_send_to"); + let env = ctx.data(); let memory = env.memory(); - let iovs_arr = wasi_try_mem_ok!(si_data.slice(memory, si_data_len)); + let iovs_arr = wasi_try_mem_ok!(si_data.slice(&ctx, memory, si_data_len)); let bytes_written = wasi_try_ok!(__sock_actor_mut( - env, + &ctx, sock, __WASI_RIGHT_SOCK_SEND_TO, - |socket| { socket.send_to::(memory, iovs_arr, addr) } + |socket| { socket.send_to::(&ctx, memory, iovs_arr, addr) } )); let bytes_written: M::Offset = wasi_try_ok!(bytes_written.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem_ok!(ret_data_len.write(memory, bytes_written as M::Offset)); + wasi_try_mem_ok!(ret_data_len.write(&ctx, memory, bytes_written as M::Offset)); Ok(__WASI_ESUCCESS) } @@ -5244,7 +5401,7 @@ pub fn sock_send_to( /// /// Number of bytes transmitted. pub unsafe fn sock_send_file( - env: &WasiEnv, + mut ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, in_fd: __wasi_fd_t, offset: __wasi_filesize_t, @@ -5252,7 +5409,8 @@ pub unsafe fn sock_send_file( ret_sent: WasmPtr<__wasi_filesize_t, M>, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::send_file"); - let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); + let env = ctx.data(); + let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); // Set the offset of the file { @@ -5341,7 +5499,7 @@ pub unsafe fn sock_send_file( // Write it down to the socket let bytes_written = wasi_try_ok!(__sock_actor_mut( - env, + &ctx, sock, __WASI_RIGHT_SOCK_SEND, |socket| { @@ -5352,7 +5510,7 @@ pub unsafe fn sock_send_file( total_written += bytes_written as u64; } - wasi_try_mem_ok!(ret_sent.write(memory, total_written as __wasi_filesize_t)); + wasi_try_mem_ok!(ret_sent.write(&ctx, memory, total_written as __wasi_filesize_t)); Ok(__WASI_ESUCCESS) } @@ -5376,7 +5534,7 @@ pub unsafe fn sock_send_file( /// /// The number of IP addresses returned during the DNS resolution. pub fn resolve( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, host: WasmPtr, host_len: M::Offset, port: u16, @@ -5387,9 +5545,10 @@ pub fn resolve( debug!("wasi::resolve"); let naddrs: usize = wasi_try!(naddrs.try_into().map_err(|_| __WASI_EINVAL)); + let env = ctx.data(); let memory = env.memory(); - let host_str = unsafe { get_input_str!(memory, host, host_len) }; - let addrs = wasi_try_mem!(addrs.slice(memory, wasi_try!(to_offset::(naddrs)))); + let host_str = unsafe { get_input_str!(&ctx, memory, host, host_len) }; + let addrs = wasi_try_mem!(addrs.slice(&ctx, memory, wasi_try!(to_offset::(naddrs)))); let port = if port > 0 { Some(port) } else { None }; @@ -5400,12 +5559,12 @@ pub fn resolve( let mut idx = 0; for found_ip in found_ips.iter().take(naddrs) { - super::state::write_ip(memory, addrs.index(idx).as_ptr::(), *found_ip); + super::state::write_ip(&ctx, memory, addrs.index(idx).as_ptr::(), *found_ip); idx += 1; } let idx: M::Offset = wasi_try!(idx.try_into().map_err(|_| __WASI_EOVERFLOW)); - wasi_try_mem!(ret_naddrs.write(memory, idx)); + wasi_try_mem!(ret_naddrs.write(&ctx, memory, idx)); __WASI_ESUCCESS } diff --git a/lib/wasi/src/syscalls/wasi.rs b/lib/wasi/src/syscalls/wasi.rs index b7d1c28edc4..14ab2200bbc 100644 --- a/lib/wasi/src/syscalls/wasi.rs +++ b/lib/wasi/src/syscalls/wasi.rs @@ -1,256 +1,260 @@ #![deny(dead_code)] use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{ContextMut, Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; use wasmer_wasi_types::*; type MemoryType = Memory32; type MemoryOffset = u32; pub(crate) fn args_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, argv: WasmPtr, MemoryType>, argv_buf: WasmPtr, ) -> __wasi_errno_t { - super::args_get::(env, argv, argv_buf) + super::args_get::(ctx, argv, argv_buf) } pub(crate) fn args_sizes_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { - super::args_sizes_get::(env, argc, argv_buf_size) + super::args_sizes_get::(ctx, argc, argv_buf_size) } pub(crate) fn clock_res_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::clock_res_get::(env, clock_id, resolution) + super::clock_res_get::(ctx, clock_id, resolution) } pub(crate) fn clock_time_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::clock_time_get::(env, clock_id, precision, time) + super::clock_time_get::(ctx, clock_id, precision, time) } pub(crate) fn environ_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ: WasmPtr, MemoryType>, environ_buf: WasmPtr, ) -> __wasi_errno_t { - super::environ_get::(env, environ, environ_buf) + super::environ_get::(ctx, environ, environ_buf) } pub(crate) fn environ_sizes_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { - super::environ_sizes_get::(env, environ_count, environ_buf_size) + super::environ_sizes_get::(ctx, environ_count, environ_buf_size) } pub(crate) fn fd_advise( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, advice: __wasi_advice_t, ) -> __wasi_errno_t { - super::fd_advise(env, fd, offset, len, advice) + super::fd_advise(ctx, fd, offset, len, advice) } pub(crate) fn fd_allocate( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, ) -> __wasi_errno_t { - super::fd_allocate(env, fd, offset, len) + super::fd_allocate(ctx, fd, offset, len) } -pub(crate) fn fd_close(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_close(env, fd) +pub(crate) fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_close(ctx, fd) } -pub(crate) fn fd_datasync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_datasync(env, fd) +pub(crate) fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_datasync(ctx, fd) } pub(crate) fn fd_fdstat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_fdstat_get::(env, fd, buf_ptr) + super::fd_fdstat_get::(ctx, fd, buf_ptr) } pub(crate) fn fd_fdstat_set_flags( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { - super::fd_fdstat_set_flags(env, fd, flags) + super::fd_fdstat_set_flags(ctx, fd, flags) } pub(crate) fn fd_fdstat_set_rights( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, ) -> __wasi_errno_t { - super::fd_fdstat_set_rights(env, fd, fs_rights_base, fs_rights_inheriting) + super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) } pub(crate) fn fd_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_filestat_get::(env, fd, buf) + super::fd_filestat_get::(ctx, fd, buf) } pub(crate) fn fd_filestat_set_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { - super::fd_filestat_set_size(env, fd, st_size) + super::fd_filestat_set_size(ctx, fd, st_size) } pub(crate) fn fd_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { - super::fd_filestat_set_times(env, fd, st_atim, st_mtim, fst_flags) + super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) } pub(crate) fn fd_pread( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, offset: __wasi_filesize_t, nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_pread::(env, fd, iovs, iovs_len, offset, nread) + super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) } pub(crate) fn fd_prestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_prestat_get::(env, fd, buf) + super::fd_prestat_get::(ctx, fd, buf) } pub(crate) fn fd_prestat_dir_name( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::fd_prestat_dir_name::(env, fd, path, path_len) + super::fd_prestat_dir_name::(ctx, fd, path, path_len) } pub(crate) fn fd_pwrite( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, offset: __wasi_filesize_t, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_pwrite::(env, fd, iovs, iovs_len, offset, nwritten) + super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) } pub(crate) fn fd_read( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_read::(env, fd, iovs, iovs_len, nread) + super::fd_read::(ctx, fd, iovs, iovs_len, nread) } pub(crate) fn fd_readdir( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr, buf_len: MemoryOffset, cookie: __wasi_dircookie_t, bufused: WasmPtr, ) -> __wasi_errno_t { - super::fd_readdir::(env, fd, buf, buf_len, cookie, bufused) + super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) } -pub(crate) fn fd_renumber(env: &WasiEnv, from: __wasi_fd_t, to: __wasi_fd_t) -> __wasi_errno_t { - super::fd_renumber(env, from, to) +pub(crate) fn fd_renumber( + ctx: ContextMut<'_, WasiEnv>, + from: __wasi_fd_t, + to: __wasi_fd_t, +) -> __wasi_errno_t { + super::fd_renumber(ctx, from, to) } pub(crate) fn fd_seek( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, newoffset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_seek::(env, fd, offset, whence, newoffset) + super::fd_seek::(ctx, fd, offset, whence, newoffset) } -pub(crate) fn fd_sync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_sync(env, fd) +pub(crate) fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_sync(ctx, fd) } pub(crate) fn fd_tell( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_tell::(env, fd, offset) + super::fd_tell::(ctx, fd, offset) } pub(crate) fn fd_write( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_write::(env, fd, iovs, iovs_len, nwritten) + super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) } pub(crate) fn path_create_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_create_directory::(env, fd, path, path_len) + super::path_create_directory::(ctx, fd, path, path_len) } pub(crate) fn path_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, path_len: MemoryOffset, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { - super::path_filestat_get::(env, fd, flags, path, path_len, buf) + super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) } pub(crate) fn path_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -260,12 +264,12 @@ pub(crate) fn path_filestat_set_times( fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { super::path_filestat_set_times::( - env, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, + ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, ) } pub(crate) fn path_link( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -275,7 +279,7 @@ pub(crate) fn path_link( new_path_len: MemoryOffset, ) -> __wasi_errno_t { super::path_link::( - env, + ctx, old_fd, old_flags, old_path, @@ -287,7 +291,7 @@ pub(crate) fn path_link( } pub(crate) fn path_open( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -299,7 +303,7 @@ pub(crate) fn path_open( fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { super::path_open::( - env, + ctx, dirfd, dirflags, path, @@ -313,7 +317,7 @@ pub(crate) fn path_open( } pub(crate) fn path_readlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -321,20 +325,20 @@ pub(crate) fn path_readlink( buf_len: MemoryOffset, buf_used: WasmPtr, ) -> __wasi_errno_t { - super::path_readlink::(env, dir_fd, path, path_len, buf, buf_len, buf_used) + super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) } pub(crate) fn path_remove_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_remove_directory::(env, fd, path, path_len) + super::path_remove_directory::(ctx, fd, path, path_len) } pub(crate) fn path_rename( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: MemoryOffset, @@ -343,7 +347,7 @@ pub(crate) fn path_rename( new_path_len: MemoryOffset, ) -> __wasi_errno_t { super::path_rename::( - env, + ctx, old_fd, old_path, old_path_len, @@ -354,57 +358,60 @@ pub(crate) fn path_rename( } pub(crate) fn path_symlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_path: WasmPtr, old_path_len: MemoryOffset, fd: __wasi_fd_t, new_path: WasmPtr, new_path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_symlink::(env, old_path, old_path_len, fd, new_path, new_path_len) + super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) } pub(crate) fn path_unlink_file( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_unlink_file::(env, fd, path, path_len) + super::path_unlink_file::(ctx, fd, path, path_len) } pub(crate) fn poll_oneoff( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, in_: WasmPtr<__wasi_subscription_t, MemoryType>, out_: WasmPtr<__wasi_event_t, MemoryType>, nsubscriptions: MemoryOffset, nevents: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::poll_oneoff::(env, in_, out_, nsubscriptions, nevents) + super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) } -pub(crate) fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) -> Result<(), WasiError> { - super::proc_exit(env, code) +pub(crate) fn proc_exit( + ctx: ContextMut<'_, WasiEnv>, + code: __wasi_exitcode_t, +) -> Result<(), WasiError> { + super::proc_exit(ctx, code) } -pub(crate) fn proc_raise(env: &WasiEnv, sig: __wasi_signal_t) -> __wasi_errno_t { - super::proc_raise(env, sig) +pub(crate) fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { + super::proc_raise(ctx, sig) } pub(crate) fn random_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, buf: WasmPtr, buf_len: MemoryOffset, ) -> __wasi_errno_t { - super::random_get::(env, buf, buf_len) + super::random_get::(ctx, buf, buf_len) } -pub(crate) fn sched_yield(env: &WasiEnv) -> Result<__wasi_errno_t, WasiError> { - super::sched_yield(env) +pub(crate) fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { + super::sched_yield(ctx) } pub(crate) fn sock_recv( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -413,7 +420,7 @@ pub(crate) fn sock_recv( ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { super::sock_recv::( - env, + ctx, sock, ri_data, ri_data_len, @@ -424,20 +431,20 @@ pub(crate) fn sock_recv( } pub(crate) fn sock_send( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, si_flags: __wasi_siflags_t, ret_data_len: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::sock_send::(env, sock, si_data, si_data_len, si_flags, ret_data_len) + super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) } pub(crate) fn sock_shutdown( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, how: __wasi_sdflags_t, ) -> __wasi_errno_t { - super::sock_shutdown(env, sock, how) + super::sock_shutdown(ctx, sock, how) } diff --git a/lib/wasi/src/syscalls/wasix32.rs b/lib/wasi/src/syscalls/wasix32.rs index 557e5c2089a..712c1a34eb9 100644 --- a/lib/wasi/src/syscalls/wasix32.rs +++ b/lib/wasi/src/syscalls/wasix32.rs @@ -1,256 +1,260 @@ #![deny(dead_code)] use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{ContextMut, Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; use wasmer_wasi_types::*; type MemoryType = Memory32; type MemoryOffset = u32; pub(crate) fn args_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, argv: WasmPtr, MemoryType>, argv_buf: WasmPtr, ) -> __wasi_errno_t { - super::args_get::(env, argv, argv_buf) + super::args_get::(ctx, argv, argv_buf) } pub(crate) fn args_sizes_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { - super::args_sizes_get::(env, argc, argv_buf_size) + super::args_sizes_get::(ctx, argc, argv_buf_size) } pub(crate) fn clock_res_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::clock_res_get::(env, clock_id, resolution) + super::clock_res_get::(ctx, clock_id, resolution) } pub(crate) fn clock_time_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::clock_time_get::(env, clock_id, precision, time) + super::clock_time_get::(ctx, clock_id, precision, time) } pub(crate) fn environ_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ: WasmPtr, MemoryType>, environ_buf: WasmPtr, ) -> __wasi_errno_t { - super::environ_get::(env, environ, environ_buf) + super::environ_get::(ctx, environ, environ_buf) } pub(crate) fn environ_sizes_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { - super::environ_sizes_get::(env, environ_count, environ_buf_size) + super::environ_sizes_get::(ctx, environ_count, environ_buf_size) } pub(crate) fn fd_advise( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, advice: __wasi_advice_t, ) -> __wasi_errno_t { - super::fd_advise(env, fd, offset, len, advice) + super::fd_advise(ctx, fd, offset, len, advice) } pub(crate) fn fd_allocate( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, ) -> __wasi_errno_t { - super::fd_allocate(env, fd, offset, len) + super::fd_allocate(ctx, fd, offset, len) } -pub(crate) fn fd_close(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_close(env, fd) +pub(crate) fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_close(ctx, fd) } -pub(crate) fn fd_datasync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_datasync(env, fd) +pub(crate) fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_datasync(ctx, fd) } pub(crate) fn fd_fdstat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_fdstat_get::(env, fd, buf_ptr) + super::fd_fdstat_get::(ctx, fd, buf_ptr) } pub(crate) fn fd_fdstat_set_flags( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { - super::fd_fdstat_set_flags(env, fd, flags) + super::fd_fdstat_set_flags(ctx, fd, flags) } pub(crate) fn fd_fdstat_set_rights( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, ) -> __wasi_errno_t { - super::fd_fdstat_set_rights(env, fd, fs_rights_base, fs_rights_inheriting) + super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) } pub(crate) fn fd_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_filestat_get::(env, fd, buf) + super::fd_filestat_get::(ctx, fd, buf) } pub(crate) fn fd_filestat_set_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { - super::fd_filestat_set_size(env, fd, st_size) + super::fd_filestat_set_size(ctx, fd, st_size) } pub(crate) fn fd_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { - super::fd_filestat_set_times(env, fd, st_atim, st_mtim, fst_flags) + super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) } pub(crate) fn fd_pread( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, offset: __wasi_filesize_t, nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_pread::(env, fd, iovs, iovs_len, offset, nread) + super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) } pub(crate) fn fd_prestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_prestat_get::(env, fd, buf) + super::fd_prestat_get::(ctx, fd, buf) } pub(crate) fn fd_prestat_dir_name( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::fd_prestat_dir_name::(env, fd, path, path_len) + super::fd_prestat_dir_name::(ctx, fd, path, path_len) } pub(crate) fn fd_pwrite( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, offset: __wasi_filesize_t, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_pwrite::(env, fd, iovs, iovs_len, offset, nwritten) + super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) } pub(crate) fn fd_read( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_read::(env, fd, iovs, iovs_len, nread) + super::fd_read::(ctx, fd, iovs, iovs_len, nread) } pub(crate) fn fd_readdir( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr, buf_len: MemoryOffset, cookie: __wasi_dircookie_t, bufused: WasmPtr, ) -> __wasi_errno_t { - super::fd_readdir::(env, fd, buf, buf_len, cookie, bufused) + super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) } -pub(crate) fn fd_renumber(env: &WasiEnv, from: __wasi_fd_t, to: __wasi_fd_t) -> __wasi_errno_t { - super::fd_renumber(env, from, to) +pub(crate) fn fd_renumber( + ctx: ContextMut<'_, WasiEnv>, + from: __wasi_fd_t, + to: __wasi_fd_t, +) -> __wasi_errno_t { + super::fd_renumber(ctx, from, to) } pub(crate) fn fd_seek( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, newoffset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_seek::(env, fd, offset, whence, newoffset) + super::fd_seek::(ctx, fd, offset, whence, newoffset) } -pub(crate) fn fd_sync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_sync(env, fd) +pub(crate) fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_sync(ctx, fd) } pub(crate) fn fd_tell( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_tell::(env, fd, offset) + super::fd_tell::(ctx, fd, offset) } pub(crate) fn fd_write( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_write::(env, fd, iovs, iovs_len, nwritten) + super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) } pub(crate) fn path_create_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_create_directory::(env, fd, path, path_len) + super::path_create_directory::(ctx, fd, path, path_len) } pub(crate) fn path_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, path_len: MemoryOffset, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { - super::path_filestat_get::(env, fd, flags, path, path_len, buf) + super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) } pub(crate) fn path_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -260,12 +264,12 @@ pub(crate) fn path_filestat_set_times( fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { super::path_filestat_set_times::( - env, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, + ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, ) } pub(crate) fn path_link( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -275,7 +279,7 @@ pub(crate) fn path_link( new_path_len: MemoryOffset, ) -> __wasi_errno_t { super::path_link::( - env, + ctx, old_fd, old_flags, old_path, @@ -287,7 +291,7 @@ pub(crate) fn path_link( } pub(crate) fn path_open( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -299,7 +303,7 @@ pub(crate) fn path_open( fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { super::path_open::( - env, + ctx, dirfd, dirflags, path, @@ -313,7 +317,7 @@ pub(crate) fn path_open( } pub(crate) fn path_readlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -321,20 +325,20 @@ pub(crate) fn path_readlink( buf_len: MemoryOffset, buf_used: WasmPtr, ) -> __wasi_errno_t { - super::path_readlink::(env, dir_fd, path, path_len, buf, buf_len, buf_used) + super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) } pub(crate) fn path_remove_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_remove_directory::(env, fd, path, path_len) + super::path_remove_directory::(ctx, fd, path, path_len) } pub(crate) fn path_rename( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: MemoryOffset, @@ -343,7 +347,7 @@ pub(crate) fn path_rename( new_path_len: MemoryOffset, ) -> __wasi_errno_t { super::path_rename::( - env, + ctx, old_fd, old_path, old_path_len, @@ -354,159 +358,168 @@ pub(crate) fn path_rename( } pub(crate) fn path_symlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_path: WasmPtr, old_path_len: MemoryOffset, fd: __wasi_fd_t, new_path: WasmPtr, new_path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_symlink::(env, old_path, old_path_len, fd, new_path, new_path_len) + super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) } pub(crate) fn path_unlink_file( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_unlink_file::(env, fd, path, path_len) + super::path_unlink_file::(ctx, fd, path, path_len) } pub(crate) fn poll_oneoff( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, in_: WasmPtr<__wasi_subscription_t, MemoryType>, out_: WasmPtr<__wasi_event_t, MemoryType>, nsubscriptions: MemoryOffset, nevents: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::poll_oneoff::(env, in_, out_, nsubscriptions, nevents) + super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) } -pub(crate) fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) -> Result<(), WasiError> { - super::proc_exit(env, code) +pub(crate) fn proc_exit( + ctx: ContextMut<'_, WasiEnv>, + code: __wasi_exitcode_t, +) -> Result<(), WasiError> { + super::proc_exit(ctx, code) } -pub(crate) fn proc_raise(env: &WasiEnv, sig: __wasi_signal_t) -> __wasi_errno_t { - super::proc_raise(env, sig) +pub(crate) fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { + super::proc_raise(ctx, sig) } pub(crate) fn random_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, buf: WasmPtr, buf_len: MemoryOffset, ) -> __wasi_errno_t { - super::random_get::(env, buf, buf_len) + super::random_get::(ctx, buf, buf_len) } pub(crate) fn fd_dup( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_dup::(env, fd, ret_fd) + super::fd_dup::(ctx, fd, ret_fd) } pub(crate) fn fd_event( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, initial_val: u64, flags: __wasi_eventfdflags, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_event(env, initial_val, flags, ret_fd) + super::fd_event(ctx, initial_val, flags, ret_fd) } pub(crate) fn fd_pipe( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ro_fd1: WasmPtr<__wasi_fd_t, MemoryType>, ro_fd2: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_pipe::(env, ro_fd1, ro_fd2) + super::fd_pipe::(ctx, ro_fd1, ro_fd2) } pub(crate) fn tty_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { - super::tty_get::(env, tty_state) + super::tty_get::(ctx, tty_state) } pub(crate) fn tty_set( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { - super::tty_set::(env, tty_state) + super::tty_set::(ctx, tty_state) } pub(crate) fn getcwd( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, path: WasmPtr, path_len: WasmPtr, ) -> __wasi_errno_t { - super::getcwd::(env, path, path_len) + super::getcwd::(ctx, path, path_len) } pub(crate) fn chdir( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::chdir::(env, path, path_len) + super::chdir::(ctx, path, path_len) } pub(crate) fn thread_spawn( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, method: WasmPtr, method_len: MemoryOffset, user_data: u64, reactor: __wasi_bool_t, ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, ) -> __wasi_errno_t { - super::thread_spawn::(env, method, method_len, user_data, reactor, ret_tid) + super::thread_spawn::(ctx, method, method_len, user_data, reactor, ret_tid) } pub(crate) fn thread_sleep( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, duration: __wasi_timestamp_t, ) -> Result<__wasi_errno_t, WasiError> { - super::thread_sleep(env, duration) + super::thread_sleep(ctx, duration) } pub(crate) fn thread_id( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, ) -> __wasi_errno_t { - super::thread_id::(env, ret_tid) + super::thread_id::(ctx, ret_tid) } -pub(crate) fn thread_join(env: &WasiEnv, tid: __wasi_tid_t) -> Result<__wasi_errno_t, WasiError> { - super::thread_join(env, tid) +pub(crate) fn thread_join( + ctx: ContextMut<'_, WasiEnv>, + tid: __wasi_tid_t, +) -> Result<__wasi_errno_t, WasiError> { + super::thread_join(ctx, tid) } pub(crate) fn thread_parallelism( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_parallelism: WasmPtr, ) -> __wasi_errno_t { - super::thread_parallelism::(env, ret_parallelism) + super::thread_parallelism::(ctx, ret_parallelism) } pub(crate) fn thread_exit( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, exitcode: __wasi_exitcode_t, ) -> Result<__wasi_errno_t, WasiError> { - super::thread_exit(env, exitcode) + super::thread_exit(ctx, exitcode) } -pub(crate) fn sched_yield(env: &WasiEnv) -> Result<__wasi_errno_t, WasiError> { - super::sched_yield(env) +pub(crate) fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { + super::sched_yield(ctx) } -pub(crate) fn getpid(env: &WasiEnv, ret_pid: WasmPtr<__wasi_pid_t, MemoryType>) -> __wasi_errno_t { - super::getpid::(env, ret_pid) +pub(crate) fn getpid( + ctx: ContextMut<'_, WasiEnv>, + ret_pid: WasmPtr<__wasi_pid_t, MemoryType>, +) -> __wasi_errno_t { + super::getpid::(ctx, ret_pid) } pub(crate) fn process_spawn( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: MemoryOffset, chroot: __wasi_bool_t, @@ -522,7 +535,7 @@ pub(crate) fn process_spawn( ret_handles: WasmPtr<__wasi_bus_handles_t, MemoryType>, ) -> __bus_errno_t { super::process_spawn::( - env, + ctx, name, name_len, chroot, @@ -540,17 +553,17 @@ pub(crate) fn process_spawn( } pub(crate) fn bus_open_local( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, ) -> __bus_errno_t { - super::bus_open_local::(env, name, name_len, reuse, ret_bid) + super::bus_open_local::(ctx, name, name_len, reuse, ret_bid) } pub(crate) fn bus_open_remote( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, @@ -561,7 +574,7 @@ pub(crate) fn bus_open_remote( ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, ) -> __bus_errno_t { super::bus_open_remote::( - env, + ctx, name, name_len, reuse, @@ -573,12 +586,12 @@ pub(crate) fn bus_open_remote( ) } -pub(crate) fn bus_close(env: &WasiEnv, bid: __wasi_bid_t) -> __bus_errno_t { - super::bus_close(env, bid) +pub(crate) fn bus_close(ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { + super::bus_close(ctx, bid) } pub(crate) fn bus_call( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -589,12 +602,12 @@ pub(crate) fn bus_call( ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, ) -> __bus_errno_t { super::bus_call::( - env, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ctx, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, ) } pub(crate) fn bus_subcall( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, parent: __wasi_cid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -605,12 +618,12 @@ pub(crate) fn bus_subcall( ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, ) -> __bus_errno_t { super::bus_subcall::( - env, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ctx, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, ) } pub(crate) fn bus_poll( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, timeout: __wasi_timestamp_t, events: WasmPtr, nevents: MemoryOffset, @@ -619,7 +632,7 @@ pub(crate) fn bus_poll( ret_nevents: WasmPtr, ) -> __bus_errno_t { super::bus_poll::( - env, + ctx, timeout, events, nevents, @@ -630,122 +643,126 @@ pub(crate) fn bus_poll( } pub(crate) fn call_reply( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t, format: __wasi_busdataformat_t, buf: WasmPtr, buf_len: MemoryOffset, ) -> __bus_errno_t { - super::call_reply::(env, cid, format, buf, buf_len) + super::call_reply::(ctx, cid, format, buf, buf_len) } -pub(crate) fn call_fault(env: &WasiEnv, cid: __wasi_cid_t, fault: __bus_errno_t) -> __bus_errno_t { - super::call_fault(env, cid, fault) +pub(crate) fn call_fault( + ctx: ContextMut<'_, WasiEnv>, + cid: __wasi_cid_t, + fault: __bus_errno_t, +) -> __bus_errno_t { + super::call_fault(ctx, cid, fault) } -pub(crate) fn call_close(env: &WasiEnv, cid: __wasi_cid_t) -> __bus_errno_t { - super::call_close(env, cid) +pub(crate) fn call_close(ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { + super::call_close(ctx, cid) } pub(crate) fn port_bridge( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, network: WasmPtr, network_len: MemoryOffset, token: WasmPtr, token_len: MemoryOffset, security: __wasi_streamsecurity_t, ) -> __wasi_errno_t { - super::port_bridge::(env, network, network_len, token, token_len, security) + super::port_bridge::(ctx, network, network_len, token, token_len, security) } -pub(crate) fn port_unbridge(env: &WasiEnv) -> __wasi_errno_t { - super::port_unbridge(env) +pub(crate) fn port_unbridge(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_unbridge(ctx) } -pub(crate) fn port_dhcp_acquire(env: &WasiEnv) -> __wasi_errno_t { - super::port_dhcp_acquire(env) +pub(crate) fn port_dhcp_acquire(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_dhcp_acquire(ctx) } pub(crate) fn port_addr_add( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, addr: WasmPtr<__wasi_cidr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_addr_add::(env, addr) + super::port_addr_add::(ctx, addr) } pub(crate) fn port_addr_remove( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, addr: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_addr_remove::(env, addr) + super::port_addr_remove::(ctx, addr) } -pub(crate) fn port_addr_clear(env: &WasiEnv) -> __wasi_errno_t { - super::port_addr_clear(env) +pub(crate) fn port_addr_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_addr_clear(ctx) } pub(crate) fn port_addr_list( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, addrs: WasmPtr<__wasi_cidr_t, MemoryType>, naddrs: WasmPtr, ) -> __wasi_errno_t { - super::port_addr_list::(env, addrs, naddrs) + super::port_addr_list::(ctx, addrs, naddrs) } pub(crate) fn port_mac( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, ) -> __wasi_errno_t { - super::port_mac::(env, ret_mac) + super::port_mac::(ctx, ret_mac) } pub(crate) fn port_gateway_set( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_gateway_set::(env, ip) + super::port_gateway_set::(ctx, ip) } pub(crate) fn port_route_add( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, cidr: WasmPtr<__wasi_cidr_t, MemoryType>, via_router: WasmPtr<__wasi_addr_t, MemoryType>, preferred_until: WasmPtr<__wasi_option_timestamp_t, MemoryType>, expires_at: WasmPtr<__wasi_option_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::port_route_add::(env, cidr, via_router, preferred_until, expires_at) + super::port_route_add::(ctx, cidr, via_router, preferred_until, expires_at) } pub(crate) fn port_route_remove( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_route_remove::(env, ip) + super::port_route_remove::(ctx, ip) } -pub(crate) fn port_route_clear(env: &WasiEnv) -> __wasi_errno_t { - super::port_route_clear(env) +pub(crate) fn port_route_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_route_clear(ctx) } pub(crate) fn port_route_list( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, routes: WasmPtr<__wasi_route_t, MemoryType>, nroutes: WasmPtr, ) -> __wasi_errno_t { - super::port_route_list::(env, routes, nroutes) + super::port_route_list::(ctx, routes, nroutes) } pub(crate) fn ws_connect( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, url: WasmPtr, url_len: MemoryOffset, ret_sock: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::ws_connect::(env, url, url_len, ret_sock) + super::ws_connect::(ctx, url, url_len, ret_sock) } pub(crate) fn http_request( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, url: WasmPtr, url_len: MemoryOffset, method: WasmPtr, @@ -756,7 +773,7 @@ pub(crate) fn http_request( ret_handles: WasmPtr<__wasi_http_handles_t, MemoryType>, ) -> __wasi_errno_t { super::http_request::( - env, + ctx, url, url_len, method, @@ -769,7 +786,7 @@ pub(crate) fn http_request( } pub(crate) fn http_status( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, status: WasmPtr<__wasi_http_status_t, MemoryType>, status_text: WasmPtr, @@ -777,169 +794,169 @@ pub(crate) fn http_status( headers: WasmPtr, headers_len: WasmPtr, ) -> __wasi_errno_t { - super::http_status::(env, sock, status) + super::http_status::(ctx, sock, status) } pub(crate) fn sock_status( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_status: WasmPtr<__wasi_sockstatus_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_status::(env, sock, ret_status) + super::sock_status::(ctx, sock, ret_status) } pub(crate) fn sock_addr_local( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_addr_local::(env, sock, ret_addr) + super::sock_addr_local::(ctx, sock, ret_addr) } pub(crate) fn sock_addr_peer( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_addr_peer::(env, sock, ro_addr) + super::sock_addr_peer::(ctx, sock, ro_addr) } pub(crate) fn sock_open( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, af: __wasi_addressfamily_t, ty: __wasi_socktype_t, pt: __wasi_sockproto_t, ro_sock: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_open::(env, af, ty, pt, ro_sock) + super::sock_open::(ctx, af, ty, pt, ro_sock) } pub(crate) fn sock_set_opt_flag( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, flag: __wasi_bool_t, ) -> __wasi_errno_t { - super::sock_set_opt_flag(env, sock, opt, flag) + super::sock_set_opt_flag(ctx, sock, opt, flag) } pub(crate) fn sock_get_opt_flag( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_flag: WasmPtr<__wasi_bool_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_get_opt_flag::(env, sock, opt, ret_flag) + super::sock_get_opt_flag::(ctx, sock, opt, ret_flag) } pub fn sock_set_opt_time( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_set_opt_time(env, sock, opt, time) + super::sock_set_opt_time(ctx, sock, opt, time) } pub fn sock_get_opt_time( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_get_opt_time(env, sock, opt, ret_time) + super::sock_get_opt_time(ctx, sock, opt, ret_time) } pub fn sock_set_opt_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, size: __wasi_filesize_t, ) -> __wasi_errno_t { - super::sock_set_opt_size(env, sock, opt, size) + super::sock_set_opt_size(ctx, sock, opt, size) } pub fn sock_get_opt_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_size: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_get_opt_size(env, sock, opt, ret_size) + super::sock_get_opt_size(ctx, sock, opt, ret_size) } pub(crate) fn sock_join_multicast_v4( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_join_multicast_v4::(env, sock, multiaddr, iface) + super::sock_join_multicast_v4::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_leave_multicast_v4( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_leave_multicast_v4::(env, sock, multiaddr, iface) + super::sock_leave_multicast_v4::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_join_multicast_v6( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, ) -> __wasi_errno_t { - super::sock_join_multicast_v6::(env, sock, multiaddr, iface) + super::sock_join_multicast_v6::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_leave_multicast_v6( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, ) -> __wasi_errno_t { - super::sock_leave_multicast_v6::(env, sock, multiaddr, iface) + super::sock_leave_multicast_v6::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_bind( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_bind::(env, sock, addr) + super::sock_bind::(ctx, sock, addr) } pub(crate) fn sock_listen( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, backlog: MemoryOffset, ) -> __wasi_errno_t { - super::sock_listen::(env, sock, backlog) + super::sock_listen::(ctx, sock, backlog) } pub(crate) fn sock_accept( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, fd_flags: __wasi_fdflags_t, ro_fd: WasmPtr<__wasi_fd_t, MemoryType>, ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { - super::sock_accept::(env, sock, fd_flags, ro_fd, ro_addr) + super::sock_accept::(ctx, sock, fd_flags, ro_fd, ro_addr) } pub(crate) fn sock_connect( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_connect::(env, sock, addr) + super::sock_connect::(ctx, sock, addr) } pub(crate) fn sock_recv( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -948,7 +965,7 @@ pub(crate) fn sock_recv( ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { super::sock_recv::( - env, + ctx, sock, ri_data, ri_data_len, @@ -959,7 +976,7 @@ pub(crate) fn sock_recv( } pub(crate) fn sock_recv_from( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -969,7 +986,7 @@ pub(crate) fn sock_recv_from( ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { super::sock_recv_from::( - env, + ctx, sock, ri_data, ri_data_len, @@ -981,18 +998,18 @@ pub(crate) fn sock_recv_from( } pub(crate) fn sock_send( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, si_flags: __wasi_siflags_t, ret_data_len: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::sock_send::(env, sock, si_data, si_data_len, si_flags, ret_data_len) + super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) } pub(crate) fn sock_send_to( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, @@ -1001,7 +1018,7 @@ pub(crate) fn sock_send_to( ret_data_len: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { super::sock_send_to::( - env, + ctx, sock, si_data, si_data_len, @@ -1012,26 +1029,26 @@ pub(crate) fn sock_send_to( } pub(crate) fn sock_send_file( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, out_fd: __wasi_fd_t, in_fd: __wasi_fd_t, offset: __wasi_filesize_t, count: __wasi_filesize_t, ret_sent: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { - unsafe { super::sock_send_file::(env, out_fd, in_fd, offset, count, ret_sent) } + unsafe { super::sock_send_file::(ctx, out_fd, in_fd, offset, count, ret_sent) } } pub(crate) fn sock_shutdown( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, how: __wasi_sdflags_t, ) -> __wasi_errno_t { - super::sock_shutdown(env, sock, how) + super::sock_shutdown(ctx, sock, how) } pub(crate) fn resolve( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, host: WasmPtr, host_len: MemoryOffset, port: u16, @@ -1039,5 +1056,5 @@ pub(crate) fn resolve( nips: MemoryOffset, ret_nips: WasmPtr, ) -> __wasi_errno_t { - super::resolve::(env, host, host_len, port, ips, nips, ret_nips) + super::resolve::(ctx, host, host_len, port, ips, nips, ret_nips) } diff --git a/lib/wasi/src/syscalls/wasix64.rs b/lib/wasi/src/syscalls/wasix64.rs index e3ece1fb80d..4064232ae6f 100644 --- a/lib/wasi/src/syscalls/wasix64.rs +++ b/lib/wasi/src/syscalls/wasix64.rs @@ -1,256 +1,260 @@ #![deny(dead_code)] use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{Memory, Memory64, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{ContextMut, Memory, Memory64, MemorySize, WasmPtr, WasmSlice}; use wasmer_wasi_types::*; type MemoryType = Memory64; type MemoryOffset = u64; pub(crate) fn args_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, argv: WasmPtr, MemoryType>, argv_buf: WasmPtr, ) -> __wasi_errno_t { - super::args_get::(env, argv, argv_buf) + super::args_get::(ctx, argv, argv_buf) } pub(crate) fn args_sizes_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { - super::args_sizes_get::(env, argc, argv_buf_size) + super::args_sizes_get::(ctx, argc, argv_buf_size) } pub(crate) fn clock_res_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::clock_res_get::(env, clock_id, resolution) + super::clock_res_get::(ctx, clock_id, resolution) } pub(crate) fn clock_time_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::clock_time_get::(env, clock_id, precision, time) + super::clock_time_get::(ctx, clock_id, precision, time) } pub(crate) fn environ_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ: WasmPtr, MemoryType>, environ_buf: WasmPtr, ) -> __wasi_errno_t { - super::environ_get::(env, environ, environ_buf) + super::environ_get::(ctx, environ, environ_buf) } pub(crate) fn environ_sizes_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { - super::environ_sizes_get::(env, environ_count, environ_buf_size) + super::environ_sizes_get::(ctx, environ_count, environ_buf_size) } pub(crate) fn fd_advise( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, advice: __wasi_advice_t, ) -> __wasi_errno_t { - super::fd_advise(env, fd, offset, len, advice) + super::fd_advise(ctx, fd, offset, len, advice) } pub(crate) fn fd_allocate( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, ) -> __wasi_errno_t { - super::fd_allocate(env, fd, offset, len) + super::fd_allocate(ctx, fd, offset, len) } -pub(crate) fn fd_close(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_close(env, fd) +pub(crate) fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_close(ctx, fd) } -pub(crate) fn fd_datasync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_datasync(env, fd) +pub(crate) fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_datasync(ctx, fd) } pub(crate) fn fd_fdstat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_fdstat_get::(env, fd, buf_ptr) + super::fd_fdstat_get::(ctx, fd, buf_ptr) } pub(crate) fn fd_fdstat_set_flags( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { - super::fd_fdstat_set_flags(env, fd, flags) + super::fd_fdstat_set_flags(ctx, fd, flags) } pub(crate) fn fd_fdstat_set_rights( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, ) -> __wasi_errno_t { - super::fd_fdstat_set_rights(env, fd, fs_rights_base, fs_rights_inheriting) + super::fd_fdstat_set_rights(ctx, fd, fs_rights_base, fs_rights_inheriting) } pub(crate) fn fd_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_filestat_get::(env, fd, buf) + super::fd_filestat_get::(ctx, fd, buf) } pub(crate) fn fd_filestat_set_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { - super::fd_filestat_set_size(env, fd, st_size) + super::fd_filestat_set_size(ctx, fd, st_size) } pub(crate) fn fd_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { - super::fd_filestat_set_times(env, fd, st_atim, st_mtim, fst_flags) + super::fd_filestat_set_times(ctx, fd, st_atim, st_mtim, fst_flags) } pub(crate) fn fd_pread( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, offset: __wasi_filesize_t, nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_pread::(env, fd, iovs, iovs_len, offset, nread) + super::fd_pread::(ctx, fd, iovs, iovs_len, offset, nread) } pub(crate) fn fd_prestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_prestat_get::(env, fd, buf) + super::fd_prestat_get::(ctx, fd, buf) } pub(crate) fn fd_prestat_dir_name( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::fd_prestat_dir_name::(env, fd, path, path_len) + super::fd_prestat_dir_name::(ctx, fd, path, path_len) } pub(crate) fn fd_pwrite( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, offset: __wasi_filesize_t, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_pwrite::(env, fd, iovs, iovs_len, offset, nwritten) + super::fd_pwrite::(ctx, fd, iovs, iovs_len, offset, nwritten) } pub(crate) fn fd_read( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, nread: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_read::(env, fd, iovs, iovs_len, nread) + super::fd_read::(ctx, fd, iovs, iovs_len, nread) } pub(crate) fn fd_readdir( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr, buf_len: MemoryOffset, cookie: __wasi_dircookie_t, bufused: WasmPtr, ) -> __wasi_errno_t { - super::fd_readdir::(env, fd, buf, buf_len, cookie, bufused) + super::fd_readdir::(ctx, fd, buf, buf_len, cookie, bufused) } -pub(crate) fn fd_renumber(env: &WasiEnv, from: __wasi_fd_t, to: __wasi_fd_t) -> __wasi_errno_t { - super::fd_renumber(env, from, to) +pub(crate) fn fd_renumber( + ctx: ContextMut<'_, WasiEnv>, + from: __wasi_fd_t, + to: __wasi_fd_t, +) -> __wasi_errno_t { + super::fd_renumber(ctx, from, to) } pub(crate) fn fd_seek( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, newoffset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_seek::(env, fd, offset, whence, newoffset) + super::fd_seek::(ctx, fd, offset, whence, newoffset) } -pub(crate) fn fd_sync(env: &WasiEnv, fd: __wasi_fd_t) -> __wasi_errno_t { - super::fd_sync(env, fd) +pub(crate) fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { + super::fd_sync(ctx, fd) } pub(crate) fn fd_tell( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_tell::(env, fd, offset) + super::fd_tell::(ctx, fd, offset) } pub(crate) fn fd_write( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, nwritten: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::fd_write::(env, fd, iovs, iovs_len, nwritten) + super::fd_write::(ctx, fd, iovs, iovs_len, nwritten) } pub(crate) fn path_create_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_create_directory::(env, fd, path, path_len) + super::path_create_directory::(ctx, fd, path, path_len) } pub(crate) fn path_filestat_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, path_len: MemoryOffset, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { - super::path_filestat_get::(env, fd, flags, path, path_len, buf) + super::path_filestat_get::(ctx, fd, flags, path, path_len, buf) } pub(crate) fn path_filestat_set_times( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -260,12 +264,12 @@ pub(crate) fn path_filestat_set_times( fst_flags: __wasi_fstflags_t, ) -> __wasi_errno_t { super::path_filestat_set_times::( - env, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, + ctx, fd, flags, path, path_len, st_atim, st_mtim, fst_flags, ) } pub(crate) fn path_link( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -275,7 +279,7 @@ pub(crate) fn path_link( new_path_len: MemoryOffset, ) -> __wasi_errno_t { super::path_link::( - env, + ctx, old_fd, old_flags, old_path, @@ -287,7 +291,7 @@ pub(crate) fn path_link( } pub(crate) fn path_open( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -299,7 +303,7 @@ pub(crate) fn path_open( fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { super::path_open::( - env, + ctx, dirfd, dirflags, path, @@ -313,7 +317,7 @@ pub(crate) fn path_open( } pub(crate) fn path_readlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -321,20 +325,20 @@ pub(crate) fn path_readlink( buf_len: MemoryOffset, buf_used: WasmPtr, ) -> __wasi_errno_t { - super::path_readlink::(env, dir_fd, path, path_len, buf, buf_len, buf_used) + super::path_readlink::(ctx, dir_fd, path, path_len, buf, buf_len, buf_used) } pub(crate) fn path_remove_directory( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_remove_directory::(env, fd, path, path_len) + super::path_remove_directory::(ctx, fd, path, path_len) } pub(crate) fn path_rename( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: MemoryOffset, @@ -343,7 +347,7 @@ pub(crate) fn path_rename( new_path_len: MemoryOffset, ) -> __wasi_errno_t { super::path_rename::( - env, + ctx, old_fd, old_path, old_path_len, @@ -354,159 +358,168 @@ pub(crate) fn path_rename( } pub(crate) fn path_symlink( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, old_path: WasmPtr, old_path_len: MemoryOffset, fd: __wasi_fd_t, new_path: WasmPtr, new_path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_symlink::(env, old_path, old_path_len, fd, new_path, new_path_len) + super::path_symlink::(ctx, old_path, old_path_len, fd, new_path, new_path_len) } pub(crate) fn path_unlink_file( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::path_unlink_file::(env, fd, path, path_len) + super::path_unlink_file::(ctx, fd, path, path_len) } pub(crate) fn poll_oneoff( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, in_: WasmPtr<__wasi_subscription_t, MemoryType>, out_: WasmPtr<__wasi_event_t, MemoryType>, nsubscriptions: MemoryOffset, nevents: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::poll_oneoff::(env, in_, out_, nsubscriptions, nevents) + super::poll_oneoff::(ctx, in_, out_, nsubscriptions, nevents) } -pub(crate) fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) -> Result<(), WasiError> { - super::proc_exit(env, code) +pub(crate) fn proc_exit( + ctx: ContextMut<'_, WasiEnv>, + code: __wasi_exitcode_t, +) -> Result<(), WasiError> { + super::proc_exit(ctx, code) } -pub(crate) fn proc_raise(env: &WasiEnv, sig: __wasi_signal_t) -> __wasi_errno_t { - super::proc_raise(env, sig) +pub(crate) fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { + super::proc_raise(ctx, sig) } pub(crate) fn random_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, buf: WasmPtr, buf_len: MemoryOffset, ) -> __wasi_errno_t { - super::random_get::(env, buf, buf_len) + super::random_get::(ctx, buf, buf_len) } pub(crate) fn fd_dup( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_dup::(env, fd, ret_fd) + super::fd_dup::(ctx, fd, ret_fd) } pub(crate) fn fd_event( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, initial_val: u64, flags: __wasi_eventfdflags, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_event(env, initial_val, flags, ret_fd) + super::fd_event(ctx, initial_val, flags, ret_fd) } pub(crate) fn fd_pipe( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ro_fd1: WasmPtr<__wasi_fd_t, MemoryType>, ro_fd2: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::fd_pipe::(env, ro_fd1, ro_fd2) + super::fd_pipe::(ctx, ro_fd1, ro_fd2) } pub(crate) fn tty_get( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { - super::tty_get::(env, tty_state) + super::tty_get::(ctx, tty_state) } pub(crate) fn tty_set( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { - super::tty_set::(env, tty_state) + super::tty_set::(ctx, tty_state) } pub(crate) fn getcwd( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, path: WasmPtr, path_len: WasmPtr, ) -> __wasi_errno_t { - super::getcwd::(env, path, path_len) + super::getcwd::(ctx, path, path_len) } pub(crate) fn chdir( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { - super::chdir::(env, path, path_len) + super::chdir::(ctx, path, path_len) } pub(crate) fn thread_spawn( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, method: WasmPtr, method_len: MemoryOffset, user_data: u64, reactor: __wasi_bool_t, ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, ) -> __wasi_errno_t { - super::thread_spawn::(env, method, method_len, user_data, reactor, ret_tid) + super::thread_spawn::(ctx, method, method_len, user_data, reactor, ret_tid) } pub(crate) fn thread_sleep( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, duration: __wasi_timestamp_t, ) -> Result<__wasi_errno_t, WasiError> { - super::thread_sleep(env, duration) + super::thread_sleep(ctx, duration) } pub(crate) fn thread_id( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, ) -> __wasi_errno_t { - super::thread_id::(env, ret_tid) + super::thread_id::(ctx, ret_tid) } -pub(crate) fn thread_join(env: &WasiEnv, tid: __wasi_tid_t) -> Result<__wasi_errno_t, WasiError> { - super::thread_join(env, tid) +pub(crate) fn thread_join( + ctx: ContextMut<'_, WasiEnv>, + tid: __wasi_tid_t, +) -> Result<__wasi_errno_t, WasiError> { + super::thread_join(ctx, tid) } pub(crate) fn thread_parallelism( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_parallelism: WasmPtr, ) -> __wasi_errno_t { - super::thread_parallelism::(env, ret_parallelism) + super::thread_parallelism::(ctx, ret_parallelism) } pub(crate) fn thread_exit( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, exitcode: __wasi_exitcode_t, ) -> Result<__wasi_errno_t, WasiError> { - super::thread_exit(env, exitcode) + super::thread_exit(ctx, exitcode) } -pub(crate) fn sched_yield(env: &WasiEnv) -> Result<__wasi_errno_t, WasiError> { - super::sched_yield(env) +pub(crate) fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { + super::sched_yield(ctx) } -pub(crate) fn getpid(env: &WasiEnv, ret_pid: WasmPtr<__wasi_pid_t, MemoryType>) -> __wasi_errno_t { - super::getpid::(env, ret_pid) +pub(crate) fn getpid( + ctx: ContextMut<'_, WasiEnv>, + ret_pid: WasmPtr<__wasi_pid_t, MemoryType>, +) -> __wasi_errno_t { + super::getpid::(ctx, ret_pid) } pub(crate) fn process_spawn( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: MemoryOffset, chroot: __wasi_bool_t, @@ -522,7 +535,7 @@ pub(crate) fn process_spawn( ret_handles: WasmPtr<__wasi_bus_handles_t, MemoryType>, ) -> __bus_errno_t { super::process_spawn::( - env, + ctx, name, name_len, chroot, @@ -540,17 +553,17 @@ pub(crate) fn process_spawn( } pub(crate) fn bus_open_local( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, ) -> __bus_errno_t { - super::bus_open_local::(env, name, name_len, reuse, ret_bid) + super::bus_open_local::(ctx, name, name_len, reuse, ret_bid) } pub(crate) fn bus_open_remote( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, @@ -561,7 +574,7 @@ pub(crate) fn bus_open_remote( ret_bid: WasmPtr<__wasi_bid_t, MemoryType>, ) -> __bus_errno_t { super::bus_open_remote::( - env, + ctx, name, name_len, reuse, @@ -573,12 +586,12 @@ pub(crate) fn bus_open_remote( ) } -pub(crate) fn bus_close(env: &WasiEnv, bid: __wasi_bid_t) -> __bus_errno_t { - super::bus_close(env, bid) +pub(crate) fn bus_close(ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { + super::bus_close(ctx, bid) } pub(crate) fn bus_call( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -589,12 +602,12 @@ pub(crate) fn bus_call( ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, ) -> __bus_errno_t { super::bus_call::( - env, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ctx, bid, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, ) } pub(crate) fn bus_subcall( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, parent: __wasi_cid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -605,12 +618,12 @@ pub(crate) fn bus_subcall( ret_cid: WasmPtr<__wasi_cid_t, MemoryType>, ) -> __bus_errno_t { super::bus_subcall::( - env, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, + ctx, parent, keep_alive, topic, topic_len, format, buf, buf_len, ret_cid, ) } pub(crate) fn bus_poll( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, timeout: __wasi_timestamp_t, events: WasmPtr, nevents: MemoryOffset, @@ -619,7 +632,7 @@ pub(crate) fn bus_poll( ret_nevents: WasmPtr, ) -> __bus_errno_t { super::bus_poll::( - env, + ctx, timeout, events, nevents, @@ -630,122 +643,126 @@ pub(crate) fn bus_poll( } pub(crate) fn call_reply( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t, format: __wasi_busdataformat_t, buf: WasmPtr, buf_len: MemoryOffset, ) -> __bus_errno_t { - super::call_reply::(env, cid, format, buf, buf_len) + super::call_reply::(ctx, cid, format, buf, buf_len) } -pub(crate) fn call_fault(env: &WasiEnv, cid: __wasi_cid_t, fault: __bus_errno_t) -> __bus_errno_t { - super::call_fault(env, cid, fault) +pub(crate) fn call_fault( + ctx: ContextMut<'_, WasiEnv>, + cid: __wasi_cid_t, + fault: __bus_errno_t, +) -> __bus_errno_t { + super::call_fault(ctx, cid, fault) } -pub(crate) fn call_close(env: &WasiEnv, cid: __wasi_cid_t) -> __bus_errno_t { - super::call_close(env, cid) +pub(crate) fn call_close(ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { + super::call_close(ctx, cid) } pub(crate) fn port_bridge( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, network: WasmPtr, network_len: MemoryOffset, token: WasmPtr, token_len: MemoryOffset, security: __wasi_streamsecurity_t, ) -> __wasi_errno_t { - super::port_bridge::(env, network, network_len, token, token_len, security) + super::port_bridge::(ctx, network, network_len, token, token_len, security) } -pub(crate) fn port_unbridge(env: &WasiEnv) -> __wasi_errno_t { - super::port_unbridge(env) +pub(crate) fn port_unbridge(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_unbridge(ctx) } -pub(crate) fn port_dhcp_acquire(env: &WasiEnv) -> __wasi_errno_t { - super::port_dhcp_acquire(env) +pub(crate) fn port_dhcp_acquire(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_dhcp_acquire(ctx) } pub(crate) fn port_addr_add( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, addr: WasmPtr<__wasi_cidr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_addr_add::(env, addr) + super::port_addr_add::(ctx, addr) } pub(crate) fn port_addr_remove( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, addr: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_addr_remove::(env, addr) + super::port_addr_remove::(ctx, addr) } -pub(crate) fn port_addr_clear(env: &WasiEnv) -> __wasi_errno_t { - super::port_addr_clear(env) +pub(crate) fn port_addr_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_addr_clear(ctx) } pub(crate) fn port_addr_list( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, addrs: WasmPtr<__wasi_cidr_t, MemoryType>, naddrs: WasmPtr, ) -> __wasi_errno_t { - super::port_addr_list::(env, addrs, naddrs) + super::port_addr_list::(ctx, addrs, naddrs) } pub(crate) fn port_mac( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, ) -> __wasi_errno_t { - super::port_mac::(env, ret_mac) + super::port_mac::(ctx, ret_mac) } pub(crate) fn port_gateway_set( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_gateway_set::(env, ip) + super::port_gateway_set::(ctx, ip) } pub(crate) fn port_route_add( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, cidr: WasmPtr<__wasi_cidr_t, MemoryType>, via_router: WasmPtr<__wasi_addr_t, MemoryType>, preferred_until: WasmPtr<__wasi_option_timestamp_t, MemoryType>, expires_at: WasmPtr<__wasi_option_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::port_route_add::(env, cidr, via_router, preferred_until, expires_at) + super::port_route_add::(ctx, cidr, via_router, preferred_until, expires_at) } pub(crate) fn port_route_remove( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { - super::port_route_remove::(env, ip) + super::port_route_remove::(ctx, ip) } -pub(crate) fn port_route_clear(env: &WasiEnv) -> __wasi_errno_t { - super::port_route_clear(env) +pub(crate) fn port_route_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { + super::port_route_clear(ctx) } pub(crate) fn port_route_list( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, routes: WasmPtr<__wasi_route_t, MemoryType>, nroutes: WasmPtr, ) -> __wasi_errno_t { - super::port_route_list::(env, routes, nroutes) + super::port_route_list::(ctx, routes, nroutes) } pub(crate) fn ws_connect( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, url: WasmPtr, url_len: MemoryOffset, ret_sock: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::ws_connect::(env, url, url_len, ret_sock) + super::ws_connect::(ctx, url, url_len, ret_sock) } pub(crate) fn http_request( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, url: WasmPtr, url_len: MemoryOffset, method: WasmPtr, @@ -756,7 +773,7 @@ pub(crate) fn http_request( ret_handles: WasmPtr<__wasi_http_handles_t, MemoryType>, ) -> __wasi_errno_t { super::http_request::( - env, + ctx, url, url_len, method, @@ -769,7 +786,7 @@ pub(crate) fn http_request( } pub(crate) fn http_status( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, status: WasmPtr<__wasi_http_status_t, MemoryType>, status_text: WasmPtr, @@ -777,169 +794,169 @@ pub(crate) fn http_status( headers: WasmPtr, headers_len: WasmPtr, ) -> __wasi_errno_t { - super::http_status::(env, sock, status) + super::http_status::(ctx, sock, status) } pub(crate) fn sock_status( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_status: WasmPtr<__wasi_sockstatus_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_status::(env, sock, ret_status) + super::sock_status::(ctx, sock, ret_status) } pub(crate) fn sock_addr_local( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_addr_local::(env, sock, ret_addr) + super::sock_addr_local::(ctx, sock, ret_addr) } pub(crate) fn sock_addr_peer( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_addr_peer::(env, sock, ro_addr) + super::sock_addr_peer::(ctx, sock, ro_addr) } pub(crate) fn sock_open( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, af: __wasi_addressfamily_t, ty: __wasi_socktype_t, pt: __wasi_sockproto_t, ro_sock: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_open::(env, af, ty, pt, ro_sock) + super::sock_open::(ctx, af, ty, pt, ro_sock) } pub(crate) fn sock_set_opt_flag( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, flag: __wasi_bool_t, ) -> __wasi_errno_t { - super::sock_set_opt_flag(env, sock, opt, flag) + super::sock_set_opt_flag(ctx, sock, opt, flag) } pub(crate) fn sock_get_opt_flag( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_flag: WasmPtr<__wasi_bool_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_get_opt_flag::(env, sock, opt, ret_flag) + super::sock_get_opt_flag::(ctx, sock, opt, ret_flag) } pub fn sock_set_opt_time( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_set_opt_time(env, sock, opt, time) + super::sock_set_opt_time(ctx, sock, opt, time) } pub fn sock_get_opt_time( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_get_opt_time(env, sock, opt, ret_time) + super::sock_get_opt_time(ctx, sock, opt, ret_time) } pub fn sock_set_opt_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, size: __wasi_filesize_t, ) -> __wasi_errno_t { - super::sock_set_opt_size(env, sock, opt, size) + super::sock_set_opt_size(ctx, sock, opt, size) } pub fn sock_get_opt_size( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_size: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_get_opt_size(env, sock, opt, ret_size) + super::sock_get_opt_size(ctx, sock, opt, ret_size) } pub(crate) fn sock_join_multicast_v4( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_join_multicast_v4::(env, sock, multiaddr, iface) + super::sock_join_multicast_v4::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_leave_multicast_v4( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_leave_multicast_v4::(env, sock, multiaddr, iface) + super::sock_leave_multicast_v4::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_join_multicast_v6( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, ) -> __wasi_errno_t { - super::sock_join_multicast_v6::(env, sock, multiaddr, iface) + super::sock_join_multicast_v6::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_leave_multicast_v6( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, ) -> __wasi_errno_t { - super::sock_leave_multicast_v6::(env, sock, multiaddr, iface) + super::sock_leave_multicast_v6::(ctx, sock, multiaddr, iface) } pub(crate) fn sock_bind( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_bind::(env, sock, addr) + super::sock_bind::(ctx, sock, addr) } pub(crate) fn sock_listen( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, backlog: MemoryOffset, ) -> __wasi_errno_t { - super::sock_listen::(env, sock, backlog) + super::sock_listen::(ctx, sock, backlog) } pub(crate) fn sock_accept( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, fd_flags: __wasi_fdflags_t, ro_fd: WasmPtr<__wasi_fd_t, MemoryType>, ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { - super::sock_accept::(env, sock, fd_flags, ro_fd, ro_addr) + super::sock_accept::(ctx, sock, fd_flags, ro_fd, ro_addr) } pub(crate) fn sock_connect( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { - super::sock_connect::(env, sock, addr) + super::sock_connect::(ctx, sock, addr) } pub(crate) fn sock_recv( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -948,7 +965,7 @@ pub(crate) fn sock_recv( ro_flags: WasmPtr<__wasi_roflags_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { super::sock_recv::( - env, + ctx, sock, ri_data, ri_data_len, @@ -959,7 +976,7 @@ pub(crate) fn sock_recv( } pub(crate) fn sock_recv_from( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -969,7 +986,7 @@ pub(crate) fn sock_recv_from( ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { super::sock_recv_from::( - env, + ctx, sock, ri_data, ri_data_len, @@ -981,18 +998,18 @@ pub(crate) fn sock_recv_from( } pub(crate) fn sock_send( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, si_flags: __wasi_siflags_t, ret_data_len: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { - super::sock_send::(env, sock, si_data, si_data_len, si_flags, ret_data_len) + super::sock_send::(ctx, sock, si_data, si_data_len, si_flags, ret_data_len) } pub(crate) fn sock_send_to( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, @@ -1001,7 +1018,7 @@ pub(crate) fn sock_send_to( ret_data_len: WasmPtr, ) -> Result<__wasi_errno_t, WasiError> { super::sock_send_to::( - env, + ctx, sock, si_data, si_data_len, @@ -1012,26 +1029,26 @@ pub(crate) fn sock_send_to( } pub(crate) fn sock_send_file( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, out_fd: __wasi_fd_t, in_fd: __wasi_fd_t, offset: __wasi_filesize_t, count: __wasi_filesize_t, ret_sent: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> Result<__wasi_errno_t, WasiError> { - unsafe { super::sock_send_file::(env, out_fd, in_fd, offset, count, ret_sent) } + unsafe { super::sock_send_file::(ctx, out_fd, in_fd, offset, count, ret_sent) } } pub(crate) fn sock_shutdown( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, sock: __wasi_fd_t, how: __wasi_sdflags_t, ) -> __wasi_errno_t { - super::sock_shutdown(env, sock, how) + super::sock_shutdown(ctx, sock, how) } pub(crate) fn resolve( - env: &WasiEnv, + ctx: ContextMut<'_, WasiEnv>, host: WasmPtr, host_len: MemoryOffset, port: u16, @@ -1039,5 +1056,5 @@ pub(crate) fn resolve( nips: MemoryOffset, ret_nips: WasmPtr, ) -> __wasi_errno_t { - super::resolve::(env, host, host_len, port, ips, nips, ret_nips) + super::resolve::(ctx, host, host_len, port, ips, nips, ret_nips) } diff --git a/tests/lib/wast/src/lib.rs b/tests/lib/wast/src/lib.rs index 0e709053ddd..4cca798b795 100644 --- a/tests/lib/wast/src/lib.rs +++ b/tests/lib/wast/src/lib.rs @@ -19,12 +19,12 @@ mod error; mod spectest; -//mod wasi_wast; +mod wasi_wast; mod wast; pub use crate::error::{DirectiveError, DirectiveErrors}; pub use crate::spectest::spectest_importobject; -//pub use crate::wasi_wast::{WasiFileSystemKind, WasiTest}; +pub use crate::wasi_wast::{WasiFileSystemKind, WasiTest}; pub use crate::wast::Wast; /// Version number of this crate. diff --git a/tests/lib/wast/src/wasi_wast.rs b/tests/lib/wast/src/wasi_wast.rs index f4e3aff5306..a9934ec3f14 100644 --- a/tests/lib/wast/src/wasi_wast.rs +++ b/tests/lib/wast/src/wasi_wast.rs @@ -3,11 +3,12 @@ use std::fs::{read_dir, File, OpenOptions, ReadDir}; use std::io::{self, Read, Seek, Write}; use std::path::{Path, PathBuf}; use std::sync::{mpsc, Arc, Mutex}; -use wasmer::{Imports, Instance, Module, Store}; +use wasmer::Context as WasmerContext; +use wasmer::{AsContextMut, ContextMut, Imports, Instance, Module, Store}; use wasmer_vfs::{host_fs, mem_fs, FileSystem}; use wasmer_wasi::types::{__wasi_filesize_t, __wasi_timestamp_t}; use wasmer_wasi::{ - generate_import_object_from_env, get_wasi_version, FsError, Pipe, VirtualFile, WasiEnv, + generate_import_object_from_ctx, get_wasi_version, FsError, Pipe, VirtualFile, WasiEnv, WasiState, WasiVersion, }; use wast::parser::{self, Parse, ParseBuffer, Parser}; @@ -83,10 +84,13 @@ impl<'a> WasiTest<'a> { }; let module = Module::new(store, &wasm_bytes)?; let (env, _tempdirs, stdout_rx, stderr_rx) = self.create_wasi_env(filesystem_kind)?; - let imports = self.get_imports(store, &module, env.clone())?; - let instance = Instance::new(&module, &imports)?; + let mut ctx = WasmerContext::new(store, env.clone()); + let imports = self.get_imports(&mut ctx.as_context_mut(), &module)?; + let instance = Instance::new(&mut ctx, &module, &imports)?; let start = instance.exports.get_function("_start")?; + let memory = instance.exports.get_memory("memory")?; + ctx.data_mut().set_memory(memory.clone()); if let Some(stdin) = &self.stdin { let state = env.state(); @@ -96,7 +100,7 @@ impl<'a> WasiTest<'a> { } // TODO: handle errors here when the error fix gets shipped - match start.call(&[]) { + match start.call(&mut ctx, &[]) { Ok(_) => {} Err(e) => { let stdout_str = get_stdio_output(&stdout_rx)?; @@ -227,9 +231,13 @@ impl<'a> WasiTest<'a> { /// Get the correct WASI import object for the given module and set it up with the /// [`WasiEnv`]. - fn get_imports(&self, store: &Store, module: &Module, env: WasiEnv) -> anyhow::Result { + fn get_imports( + &self, + ctx: &mut ContextMut<'_, WasiEnv>, + module: &Module, + ) -> anyhow::Result { let version = self.get_version(module)?; - Ok(generate_import_object_from_env(store, env, version)) + Ok(generate_import_object_from_ctx(ctx, version)) } } From cf85615e559f2512a500c3f2ba6f05286da4fc9a Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Tue, 31 May 2022 17:23:51 +0200 Subject: [PATCH 07/24] Ported Emscripten to new Context API --- Cargo.lock | 1 + lib/emscripten/Cargo.toml | 3 +- lib/emscripten/src/bitwise.rs | 3 +- lib/emscripten/src/emscripten_target.rs | 287 +++-- lib/emscripten/src/env/mod.rs | 71 +- lib/emscripten/src/env/unix/mod.rs | 95 +- lib/emscripten/src/errno.rs | 3 +- lib/emscripten/src/exception.rs | 21 +- lib/emscripten/src/exec.rs | 26 +- lib/emscripten/src/exit.rs | 3 +- lib/emscripten/src/inet.rs | 3 +- lib/emscripten/src/io/mod.rs | 21 +- lib/emscripten/src/io/unix.rs | 30 +- lib/emscripten/src/jmp.rs | 23 +- lib/emscripten/src/lib.rs | 1571 ++++++++++++++--------- lib/emscripten/src/libc.rs | 31 +- lib/emscripten/src/linking.rs | 9 +- lib/emscripten/src/lock.rs | 15 +- lib/emscripten/src/macros.rs | 4 +- lib/emscripten/src/math.rs | 43 +- lib/emscripten/src/memory.rs | 70 +- lib/emscripten/src/process.rs | 71 +- lib/emscripten/src/pthread.rs | 80 +- lib/emscripten/src/signal.rs | 19 +- lib/emscripten/src/syscalls/mod.rs | 286 +++-- lib/emscripten/src/syscalls/unix.rs | 434 +++---- lib/emscripten/src/time.rs | 101 +- lib/emscripten/src/ucontext.rs | 15 +- lib/emscripten/src/unistd.rs | 3 +- lib/emscripten/src/utils.rs | 62 +- lib/emscripten/src/varargs.rs | 12 +- 31 files changed, 2034 insertions(+), 1382 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c459767073..6ed8a3404bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3018,6 +3018,7 @@ dependencies = [ "log", "time", "wasmer", + "wasmer-types", ] [[package]] diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 17e8f14b5cb..ed504976374 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -16,7 +16,8 @@ lazy_static = "1.4" libc = "^0.2" log = "0.4" time = { version = "0.2", features = ["std"] } -wasmer = { path = "../api", version = "=2.3.0", default-features = false, features = ["sys"] } +wasmer = { path = "../api", version = "=2.3.0", default-features = false, features = ["sys", "compiler"] } +wasmer-types = { path = "../types", version = "=2.3.0" } [target.'cfg(windows)'.dependencies] getrandom = "0.2" diff --git a/lib/emscripten/src/bitwise.rs b/lib/emscripten/src/bitwise.rs index 5343dfe1c49..be6ee40be01 100644 --- a/lib/emscripten/src/bitwise.rs +++ b/lib/emscripten/src/bitwise.rs @@ -1,8 +1,9 @@ use crate::emscripten_target; use crate::EmEnv; +use wasmer::ContextMut; ///emscripten: _llvm_bswap_i64 -pub fn _llvm_bswap_i64(ctx: &EmEnv, _low: i32, high: i32) -> i32 { +pub fn _llvm_bswap_i64(ctx: ContextMut<'_, EmEnv>, _low: i32, high: i32) -> i32 { debug!("emscripten::_llvm_bswap_i64"); emscripten_target::setTempRet0(ctx, _low.swap_bytes()); high.swap_bytes() diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs index c4b3aff8d90..e299e862b7c 100644 --- a/lib/emscripten/src/emscripten_target.rs +++ b/lib/emscripten/src/emscripten_target.rs @@ -1,35 +1,36 @@ #![allow(non_snake_case)] -use crate::env::get_emscripten_data; +use crate::env::{get_emscripten_data, get_emscripten_funcs}; use crate::EmEnv; #[cfg(target_os = "linux")] use libc::getdtablesize; +use wasmer::{AsContextMut, ContextMut}; -pub fn asm_const_i(_ctx: &EmEnv, _val: i32) -> i32 { +pub fn asm_const_i(_ctx: ContextMut<'_, EmEnv>, _val: i32) -> i32 { debug!("emscripten::asm_const_i: {}", _val); 0 } -pub fn exit_with_live_runtime(_ctx: &EmEnv) { +pub fn exit_with_live_runtime(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::exit_with_live_runtime"); } -pub fn setTempRet0(ctx: &EmEnv, val: i32) { +pub fn setTempRet0(ctx: ContextMut<'_, EmEnv>, val: i32) { trace!("emscripten::setTempRet0: {}", val); - get_emscripten_data(ctx).temp_ret_0 = val; + get_emscripten_data(&ctx).temp_ret_0 = val; } -pub fn getTempRet0(ctx: &EmEnv) -> i32 { +pub fn getTempRet0(ctx: ContextMut<'_, EmEnv>) -> i32 { trace!("emscripten::getTempRet0"); - get_emscripten_data(ctx).temp_ret_0 + get_emscripten_data(&ctx).temp_ret_0 } -pub fn _alarm(_ctx: &EmEnv, _seconds: u32) -> i32 { +pub fn _alarm(_ctx: ContextMut<'_, EmEnv>, _seconds: u32) -> i32 { debug!("emscripten::_alarm({})", _seconds); 0 } -pub fn _atexit(_ctx: &EmEnv, _func: i32) -> i32 { +pub fn _atexit(_ctx: ContextMut<'_, EmEnv>, _func: i32) -> i32 { debug!("emscripten::_atexit"); // TODO: implement atexit properly // __ATEXIT__.unshift({ @@ -38,38 +39,38 @@ pub fn _atexit(_ctx: &EmEnv, _func: i32) -> i32 { // }); 0 } -pub fn __Unwind_Backtrace(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn __Unwind_Backtrace(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::__Unwind_Backtrace"); 0 } -pub fn __Unwind_FindEnclosingFunction(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn __Unwind_FindEnclosingFunction(_ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { debug!("emscripten::__Unwind_FindEnclosingFunction"); 0 } -pub fn __Unwind_GetIPInfo(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn __Unwind_GetIPInfo(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::__Unwind_GetIPInfo"); 0 } -pub fn ___cxa_find_matching_catch_2(_ctx: &EmEnv) -> i32 { +pub fn ___cxa_find_matching_catch_2(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::___cxa_find_matching_catch_2"); 0 } -pub fn ___cxa_find_matching_catch_3(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn ___cxa_find_matching_catch_3(_ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { debug!("emscripten::___cxa_find_matching_catch_3"); 0 } -pub fn ___cxa_free_exception(_ctx: &EmEnv, _a: i32) { +pub fn ___cxa_free_exception(_ctx: ContextMut<'_, EmEnv>, _a: i32) { debug!("emscripten::___cxa_free_exception"); } -pub fn ___resumeException(_ctx: &EmEnv, _a: i32) { +pub fn ___resumeException(_ctx: ContextMut<'_, EmEnv>, _a: i32) { debug!("emscripten::___resumeException"); } -pub fn _dladdr(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _dladdr(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::_dladdr"); 0 } pub fn ___gxx_personality_v0( - _ctx: &EmEnv, + _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32, @@ -82,25 +83,25 @@ pub fn ___gxx_personality_v0( } #[cfg(target_os = "linux")] -pub fn _getdtablesize(_ctx: &EmEnv) -> i32 { +pub fn _getdtablesize(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::getdtablesize"); unsafe { getdtablesize() } } #[cfg(not(target_os = "linux"))] -pub fn _getdtablesize(_ctx: &EmEnv) -> i32 { +pub fn _getdtablesize(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::getdtablesize"); -1 } -pub fn _gethostbyaddr(_ctx: &EmEnv, _addr: i32, _addrlen: i32, _atype: i32) -> i32 { +pub fn _gethostbyaddr(_ctx: ContextMut<'_, EmEnv>, _addr: i32, _addrlen: i32, _atype: i32) -> i32 { debug!("emscripten::gethostbyaddr"); 0 } -pub fn _gethostbyname(_ctx: &EmEnv, _name: i32) -> i32 { +pub fn _gethostbyname(_ctx: ContextMut<'_, EmEnv>, _name: i32) -> i32 { debug!("emscripten::gethostbyname_r"); 0 } pub fn _gethostbyname_r( - _ctx: &EmEnv, + _ctx: ContextMut<'_, EmEnv>, _name: i32, _ret: i32, _buf: i32, @@ -112,13 +113,13 @@ pub fn _gethostbyname_r( 0 } // NOTE: php.js has proper impl; libc has proper impl for linux -pub fn _getloadavg(_ctx: &EmEnv, _loadavg: i32, _nelem: i32) -> i32 { +pub fn _getloadavg(_ctx: ContextMut<'_, EmEnv>, _loadavg: i32, _nelem: i32) -> i32 { debug!("emscripten::getloadavg"); 0 } #[allow(clippy::too_many_arguments)] pub fn _getnameinfo( - _ctx: &EmEnv, + _ctx: ContextMut<'_, EmEnv>, _addr: i32, _addrlen: i32, _host: i32, @@ -140,15 +141,18 @@ pub fn _getnameinfo( // Macro definitions macro_rules! invoke { ($ctx: ident, $name:ident, $name_ref:ident, $( $arg:ident ),*) => {{ - let sp = get_emscripten_data($ctx).stack_save_ref().expect("stack_save is None").call().expect("stack_save call failed"); - let call = get_emscripten_data($ctx).$name_ref().expect(concat!("Dynamic call is None: ", stringify!($name))).clone(); - match call.call($($arg),*) { + let funcs = get_emscripten_funcs(&$ctx).clone(); + let sp = funcs.stack_save_ref().expect("stack_save is None").call(&mut $ctx.as_context_mut()).expect("stack_save call failed"); + let call = funcs.$name_ref().expect(concat!("Dynamic call is None: ", stringify!($name))).clone(); + match call.call(&mut $ctx, $($arg),*) { Ok(v) => v, Err(_e) => { - get_emscripten_data($ctx).stack_restore_ref().expect("stack_restore is None").call(sp).expect("stack_restore call failed"); + let stack = funcs.stack_restore_ref().expect("stack_restore is None"); + stack.call(&mut $ctx, sp).expect("stack_restore call failed"); // TODO: We should check if _e != "longjmp" and if that's the case, re-throw the error // JS version is: if (e !== e+0 && e !== 'longjmp') throw e; - get_emscripten_data($ctx).set_threw_ref().expect("set_threw is None").call(1, 0).expect("set_threw call failed"); + let threw = funcs.set_threw_ref().expect("set_threw is None"); + threw.call(&mut $ctx, 1, 0).expect("set_threw call failed"); 0 as _ } } @@ -156,15 +160,19 @@ macro_rules! invoke { } macro_rules! invoke_no_return { ($ctx: ident, $name:ident, $name_ref:ident, $( $arg:ident ),*) => {{ - let sp = get_emscripten_data($ctx).stack_save_ref().expect("stack_save is None").call().expect("stack_save call failed"); - let call = get_emscripten_data($ctx).$name_ref().expect(concat!("Dynamic call is None: ", stringify!($name))).clone(); - match call.call($($arg),*) { + let funcs = get_emscripten_funcs(&$ctx).clone(); + let stack = funcs.stack_save_ref().expect("stack_save is None"); + let sp = stack.call(&mut $ctx).expect("stack_save call failed"); + let call = funcs.$name_ref().expect(concat!("Dynamic call is None: ", stringify!($name))).clone(); + match call.call(&mut $ctx, $($arg),*) { Ok(v) => v, Err(_e) => { - get_emscripten_data($ctx).stack_restore_ref().expect("stack_restore is None").call(sp).expect("stack_restore call failed"); + let stack = funcs.stack_restore_ref().expect("stack_restore is None"); + stack.call(&mut $ctx, sp).expect("stack_restore call failed"); // TODO: We should check if _e != "longjmp" and if that's the case, re-throw the error // JS version is: if (e !== e+0 && e !== 'longjmp') throw e; - get_emscripten_data($ctx).set_threw_ref().expect("set_threw is None").call(1, 0).expect("set_threw call failed"); + let threw = funcs.set_threw_ref().expect("set_threw is None"); + threw.call(&mut $ctx, 1, 0).expect("set_threw call failed"); } } }}; @@ -172,51 +180,59 @@ macro_rules! invoke_no_return { // The invoke_j functions do not save the stack macro_rules! invoke_no_stack_save { ($ctx: ident, $name:ident, $name_ref:ident, $( $arg:ident ),*) => {{ - let call = get_emscripten_data($ctx).$name_ref().expect(concat!(stringify!($name), " is set to None")).clone(); + let funcs = get_emscripten_funcs(&$ctx).clone(); + let call = funcs.$name_ref().expect(concat!(stringify!($name), " is set to None")).clone(); - call.call($($arg),*).unwrap() + call.call(&mut $ctx.as_context_mut(), $($arg),*).unwrap() }} } // Invoke functions -pub fn invoke_i(ctx: &EmEnv, index: i32) -> i32 { +pub fn invoke_i(mut ctx: ContextMut<'_, EmEnv>, index: i32) -> i32 { debug!("emscripten::invoke_i"); invoke!(ctx, dyn_call_i, dyn_call_i_ref, index) } -pub fn invoke_ii(ctx: &EmEnv, index: i32, a1: i32) -> i32 { +pub fn invoke_ii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32) -> i32 { debug!("emscripten::invoke_ii"); invoke!(ctx, dyn_call_ii, dyn_call_ii_ref, index, a1) } -pub fn invoke_iii(ctx: &EmEnv, index: i32, a1: i32, a2: i32) -> i32 { +pub fn invoke_iii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) -> i32 { debug!("emscripten::invoke_iii"); invoke!(ctx, dyn_call_iii, dyn_call_iii_ref, index, a1, a2) } -pub fn invoke_iiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_iiii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_iiii"); invoke!(ctx, dyn_call_iiii, dyn_call_iiii_ref, index, a1, a2, a3) } -pub fn invoke_iifi(ctx: &EmEnv, index: i32, a1: i32, a2: f64, a3: i32) -> i32 { +pub fn invoke_iifi(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: f64, a3: i32) -> i32 { debug!("emscripten::invoke_iifi"); invoke!(ctx, dyn_call_iifi, dyn_call_iifi_ref, index, a1, a2, a3) } -pub fn invoke_v(ctx: &EmEnv, index: i32) { +pub fn invoke_v(mut ctx: ContextMut<'_, EmEnv>, index: i32) { debug!("emscripten::invoke_v"); invoke_no_return!(ctx, dyn_call_v, dyn_call_v_ref, index); } -pub fn invoke_vi(ctx: &EmEnv, index: i32, a1: i32) { +pub fn invoke_vi(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32) { debug!("emscripten::invoke_vi"); invoke_no_return!(ctx, dyn_call_vi, dyn_call_vi_ref, index, a1); } -pub fn invoke_vii(ctx: &EmEnv, index: i32, a1: i32, a2: i32) { +pub fn invoke_vii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) { debug!("emscripten::invoke_vii"); invoke_no_return!(ctx, dyn_call_vii, dyn_call_vii_ref, index, a1, a2); } -pub fn invoke_viii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32) { +pub fn invoke_viii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) { debug!("emscripten::invoke_viii"); invoke_no_return!(ctx, dyn_call_viii, dyn_call_viii_ref, index, a1, a2, a3); } -pub fn invoke_viiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { +pub fn invoke_viiii( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, +) { debug!("emscripten::invoke_viiii"); invoke_no_return!( ctx, @@ -229,11 +245,18 @@ pub fn invoke_viiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) a4 ); } -pub fn invoke_dii(ctx: &EmEnv, index: i32, a1: i32, a2: i32) -> f64 { +pub fn invoke_dii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) -> f64 { debug!("emscripten::invoke_dii"); invoke!(ctx, dyn_call_dii, dyn_call_dii_ref, index, a1, a2) } -pub fn invoke_diiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> f64 { +pub fn invoke_diiii( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, +) -> f64 { debug!("emscripten::invoke_diiii"); invoke!( ctx, @@ -246,7 +269,14 @@ pub fn invoke_diiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) a4 ) } -pub fn invoke_iiiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 { +pub fn invoke_iiiii( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, +) -> i32 { debug!("emscripten::invoke_iiiii"); invoke!( ctx, @@ -259,7 +289,15 @@ pub fn invoke_iiiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) a4 ) } -pub fn invoke_iiiiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) -> i32 { +pub fn invoke_iiiiii( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, +) -> i32 { debug!("emscripten::invoke_iiiiii"); invoke!( ctx, @@ -275,7 +313,7 @@ pub fn invoke_iiiiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32 } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -300,7 +338,7 @@ pub fn invoke_iiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -327,7 +365,7 @@ pub fn invoke_iiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -356,7 +394,7 @@ pub fn invoke_iiiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -387,7 +425,7 @@ pub fn invoke_iiiiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -418,11 +456,19 @@ pub fn invoke_iiiiiiiiiii( a10 ) } -pub fn invoke_vd(ctx: &EmEnv, index: i32, a1: f64) { +pub fn invoke_vd(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: f64) { debug!("emscripten::invoke_vd"); invoke_no_return!(ctx, dyn_call_vd, dyn_call_vd_ref, index, a1) } -pub fn invoke_viiiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { +pub fn invoke_viiiii( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, +) { debug!("emscripten::invoke_viiiii"); invoke_no_return!( ctx, @@ -438,7 +484,7 @@ pub fn invoke_viiiii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32 } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -463,7 +509,7 @@ pub fn invoke_viiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -490,7 +536,7 @@ pub fn invoke_viiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -519,7 +565,7 @@ pub fn invoke_viiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -550,7 +596,7 @@ pub fn invoke_viiiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -582,24 +628,31 @@ pub fn invoke_viiiiiiiiii( ) } -pub fn invoke_iij(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_iij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_iij"); invoke!(ctx, dyn_call_iij, dyn_call_iij_ref, index, a1, a2, a3) } -pub fn invoke_iji(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_iji(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_iji"); invoke!(ctx, dyn_call_iji, dyn_call_iji_ref, index, a1, a2, a3) } -pub fn invoke_iiji(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 { +pub fn invoke_iiji( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, +) -> i32 { debug!("emscripten::invoke_iiji"); invoke!(ctx, dyn_call_iiji, dyn_call_iiji_ref, index, a1, a2, a3, a4) } #[allow(clippy::too_many_arguments)] pub fn invoke_iiijj( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -622,28 +675,43 @@ pub fn invoke_iiijj( a6 ) } -pub fn invoke_j(ctx: &EmEnv, index: i32) -> i32 { +pub fn invoke_j(mut ctx: ContextMut<'_, EmEnv>, index: i32) -> i32 { debug!("emscripten::invoke_j"); invoke_no_stack_save!(ctx, dyn_call_j, dyn_call_j_ref, index) } -pub fn invoke_ji(ctx: &EmEnv, index: i32, a1: i32) -> i32 { +pub fn invoke_ji(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32) -> i32 { debug!("emscripten::invoke_ji"); invoke_no_stack_save!(ctx, dyn_call_ji, dyn_call_ji_ref, index, a1) } -pub fn invoke_jii(ctx: &EmEnv, index: i32, a1: i32, a2: i32) -> i32 { +pub fn invoke_jii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) -> i32 { debug!("emscripten::invoke_jii"); invoke_no_stack_save!(ctx, dyn_call_jii, dyn_call_jii_ref, index, a1, a2) } -pub fn invoke_jij(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_jij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_jij"); invoke_no_stack_save!(ctx, dyn_call_jij, dyn_call_jij_ref, index, a1, a2, a3) } -pub fn invoke_jjj(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) -> i32 { +pub fn invoke_jjj( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, +) -> i32 { debug!("emscripten::invoke_jjj"); invoke_no_stack_save!(ctx, dyn_call_jjj, dyn_call_jjj_ref, index, a1, a2, a3, a4) } -pub fn invoke_viiij(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { +pub fn invoke_viiij( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, +) { debug!("emscripten::invoke_viiij"); invoke_no_stack_save!( ctx, @@ -659,7 +727,7 @@ pub fn invoke_viiij(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, } #[allow(clippy::too_many_arguments)] pub fn invoke_viiijiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -690,7 +758,7 @@ pub fn invoke_viiijiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiijiiiiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -723,11 +791,19 @@ pub fn invoke_viiijiiiiii( a11 ) } -pub fn invoke_viij(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { +pub fn invoke_viij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { debug!("emscripten::invoke_viij"); invoke_no_stack_save!(ctx, dyn_call_viij, dyn_call_viij_ref, index, a1, a2, a3, a4) } -pub fn invoke_viiji(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { +pub fn invoke_viiji( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, +) { debug!("emscripten::invoke_viiji"); invoke_no_stack_save!( ctx, @@ -743,7 +819,7 @@ pub fn invoke_viiji(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, } #[allow(clippy::too_many_arguments)] pub fn invoke_viijiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -769,7 +845,16 @@ pub fn invoke_viijiii( ) } #[allow(clippy::too_many_arguments)] -pub fn invoke_viijj(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32, a6: i32) { +pub fn invoke_viijj( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, +) { debug!("emscripten::invoke_viijj"); invoke_no_stack_save!( ctx, @@ -784,11 +869,19 @@ pub fn invoke_viijj(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a6 ) } -pub fn invoke_vj(ctx: &EmEnv, index: i32, a1: i32, a2: i32) { +pub fn invoke_vj(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) { debug!("emscripten::invoke_vj"); invoke_no_stack_save!(ctx, dyn_call_vj, dyn_call_vj_ref, index, a1, a2) } -pub fn invoke_vjji(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { +pub fn invoke_vjji( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, +) { debug!("emscripten::invoke_vjji"); invoke_no_return!( ctx, @@ -802,17 +895,17 @@ pub fn invoke_vjji(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5 ) } -pub fn invoke_vij(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32) { +pub fn invoke_vij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) { debug!("emscripten::invoke_vij"); invoke_no_stack_save!(ctx, dyn_call_vij, dyn_call_vij_ref, index, a1, a2, a3) } -pub fn invoke_viji(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { +pub fn invoke_viji(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { debug!("emscripten::invoke_viji"); invoke_no_stack_save!(ctx, dyn_call_viji, dyn_call_viji_ref, index, a1, a2, a3, a4) } #[allow(clippy::too_many_arguments)] pub fn invoke_vijiii( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, @@ -835,7 +928,15 @@ pub fn invoke_vijiii( a6 ) } -pub fn invoke_vijj(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) { +pub fn invoke_vijj( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, +) { debug!("emscripten::invoke_vijj"); invoke_no_stack_save!( ctx, @@ -849,15 +950,23 @@ pub fn invoke_vijj(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: i32, a4: i32, a5 ) } -pub fn invoke_vidd(ctx: &EmEnv, index: i32, a1: i32, a2: f64, a3: f64) { +pub fn invoke_vidd(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: f64, a3: f64) { debug!("emscripten::invoke_viid"); invoke_no_return!(ctx, dyn_call_vidd, dyn_call_vidd_ref, index, a1, a2, a3); } -pub fn invoke_viid(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: f64) { +pub fn invoke_viid(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: f64) { debug!("emscripten::invoke_viid"); invoke_no_return!(ctx, dyn_call_viid, dyn_call_viid_ref, index, a1, a2, a3); } -pub fn invoke_viidii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: f64, a4: i32, a5: i32) { +pub fn invoke_viidii( + mut ctx: ContextMut<'_, EmEnv>, + index: i32, + a1: i32, + a2: i32, + a3: f64, + a4: i32, + a5: i32, +) { debug!("emscripten::invoke_viidii"); invoke_no_return!( ctx, @@ -873,7 +982,7 @@ pub fn invoke_viidii(ctx: &EmEnv, index: i32, a1: i32, a2: i32, a3: f64, a4: i32 } #[allow(clippy::too_many_arguments)] pub fn invoke_viidddddddd( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 71e4011ca9a..5985293941b 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -12,54 +12,55 @@ pub use self::windows::*; use libc::c_char; -use crate::{allocate_on_stack, EmscriptenData}; +use crate::{allocate_on_stack, EmscriptenData, EmscriptenFunctions}; use std::os::raw::c_int; use std::sync::MutexGuard; use crate::EmEnv; use wasmer::ValueType; -use wasmer::WasmPtr; +use wasmer::{AsContextMut, ContextMut, WasmPtr}; -pub fn call_malloc(ctx: &EmEnv, size: u32) -> u32 { - get_emscripten_data(ctx) - .malloc_ref() - .unwrap() - .call(size) - .unwrap() +pub fn call_malloc(mut ctx: ContextMut<'_, EmEnv>, size: u32) -> u32 { + let malloc_ref = get_emscripten_funcs(&ctx).malloc_ref().unwrap().clone(); + malloc_ref.call(&mut ctx.as_context_mut(), size).unwrap() } #[warn(dead_code)] -pub fn call_malloc_with_cast(ctx: &EmEnv, size: u32) -> WasmPtr { +pub fn call_malloc_with_cast(ctx: ContextMut<'_, EmEnv>, size: u32) -> WasmPtr { WasmPtr::new(call_malloc(ctx, size)) } -pub fn call_memalign(ctx: &EmEnv, alignment: u32, size: u32) -> u32 { - if let Some(memalign) = &get_emscripten_data(ctx).memalign_ref() { - memalign.call(alignment, size).unwrap() - } else { - panic!("Memalign is set to None"); - } +pub fn call_memalign(mut ctx: ContextMut<'_, EmEnv>, alignment: u32, size: u32) -> u32 { + let memalign_ref = get_emscripten_funcs(&ctx).memalign_ref().unwrap().clone(); + memalign_ref.call(&mut ctx, alignment, size).unwrap() } -pub fn call_memset(ctx: &EmEnv, pointer: u32, value: u32, size: u32) -> u32 { - get_emscripten_data(ctx) - .memset_ref() - .unwrap() - .call(pointer, value, size) +pub fn call_memset(mut ctx: ContextMut<'_, EmEnv>, pointer: u32, value: u32, size: u32) -> u32 { + let memset_ref = get_emscripten_funcs(&ctx).memset_ref().unwrap().clone(); + memset_ref + .call(&mut ctx.as_context_mut(), pointer, value, size) .unwrap() } -pub(crate) fn get_emscripten_data(ctx: &EmEnv) -> MutexGuard { - ctx.data.lock().unwrap() +pub(crate) fn get_emscripten_data<'a>( + ctx: &'a ContextMut<'_, EmEnv>, +) -> MutexGuard<'a, EmscriptenData> { + ctx.data().data.lock().unwrap() +} + +pub(crate) fn get_emscripten_funcs<'a>( + ctx: &'a ContextMut<'_, EmEnv>, +) -> MutexGuard<'a, EmscriptenFunctions> { + ctx.data().funcs.lock().unwrap() } -pub fn _getpagesize(_ctx: &EmEnv) -> u32 { +pub fn _getpagesize(_ctx: ContextMut<'_, EmEnv>) -> u32 { debug!("emscripten::_getpagesize"); 16384 } -pub fn _times(ctx: &EmEnv, buffer: u32) -> u32 { +pub fn _times(ctx: ContextMut<'_, EmEnv>, buffer: u32) -> u32 { if buffer != 0 { call_memset(ctx, buffer, 0, 16); } @@ -67,18 +68,20 @@ pub fn _times(ctx: &EmEnv, buffer: u32) -> u32 { } #[allow(clippy::cast_ptr_alignment)] -pub fn ___build_environment(ctx: &EmEnv, environ: c_int) { +pub fn ___build_environment(mut ctx: ContextMut<'_, EmEnv>, environ: c_int) { debug!("emscripten::___build_environment {}", environ); const MAX_ENV_VALUES: u32 = 64; const TOTAL_ENV_SIZE: u32 = 1024; - let environment = emscripten_memory_pointer!(ctx.memory(0), environ) as *mut c_int; + let environment = emscripten_memory_pointer!(ctx, ctx.data().memory(0), environ) as *mut c_int; let (mut pool_offset, env_ptr, mut pool_ptr) = unsafe { let (pool_offset, _pool_slice): (u32, &mut [u8]) = - allocate_on_stack(ctx, TOTAL_ENV_SIZE as u32); + allocate_on_stack(&mut ctx.as_context_mut(), TOTAL_ENV_SIZE as u32); let (env_offset, _env_slice): (u32, &mut [u8]) = - allocate_on_stack(ctx, (MAX_ENV_VALUES * 4) as u32); - let env_ptr = emscripten_memory_pointer!(ctx.memory(0), env_offset) as *mut c_int; - let pool_ptr = emscripten_memory_pointer!(ctx.memory(0), pool_offset) as *mut u8; + allocate_on_stack(&mut ctx.as_context_mut(), (MAX_ENV_VALUES * 4) as u32); + let env_ptr = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), env_offset) as *mut c_int; + let pool_ptr = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), pool_offset) as *mut u8; *env_ptr = pool_offset as i32; *environment = env_offset as i32; @@ -119,18 +122,18 @@ pub fn ___build_environment(ctx: &EmEnv, environ: c_int) { } } -pub fn ___assert_fail(_ctx: &EmEnv, _a: c_int, _b: c_int, _c: c_int, _d: c_int) { +pub fn ___assert_fail(_ctx: ContextMut<'_, EmEnv>, _a: c_int, _b: c_int, _c: c_int, _d: c_int) { debug!("emscripten::___assert_fail {} {} {} {}", _a, _b, _c, _d); // TODO: Implement like emscripten expects regarding memory/page size // TODO raise an error } -pub fn _pathconf(ctx: &EmEnv, path_addr: c_int, name: c_int) -> c_int { +pub fn _pathconf(ctx: ContextMut<'_, EmEnv>, path_addr: c_int, name: c_int) -> c_int { debug!( "emscripten::_pathconf {} {} - UNIMPLEMENTED", path_addr, name ); - let _path = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const c_char; + let _path = emscripten_memory_pointer!(ctx, ctx.data().memory(0), path_addr) as *const c_char; match name { 0 => 32000, 1 | 2 | 3 => 255, @@ -146,7 +149,7 @@ pub fn _pathconf(ctx: &EmEnv, path_addr: c_int, name: c_int) -> c_int { } } -pub fn _fpathconf(_ctx: &EmEnv, _fildes: c_int, name: c_int) -> c_int { +pub fn _fpathconf(_ctx: ContextMut<'_, EmEnv>, _fildes: c_int, name: c_int) -> c_int { debug!("emscripten::_fpathconf {} {}", _fildes, name); match name { 0 => 32000, diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs index c41521f1240..9ef7e59a024 100644 --- a/lib/emscripten/src/env/unix/mod.rs +++ b/lib/emscripten/src/env/unix/mod.rs @@ -10,14 +10,14 @@ use std::os::raw::c_char; use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr}; use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs}; use crate::EmEnv; -use wasmer::WasmPtr; +use wasmer::{AsContextMut, ContextMut, WasmPtr}; // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; -pub fn _getenv(ctx: &EmEnv, name: i32) -> u32 { +pub fn _getenv(ctx: ContextMut<'_, EmEnv>, name: i32) -> u32 { debug!("emscripten::_getenv"); - let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); @@ -30,11 +30,11 @@ pub fn _getenv(ctx: &EmEnv, name: i32) -> u32 { } /// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int); -pub fn _setenv(ctx: &EmEnv, name: c_int, value: c_int, overwrite: c_int) -> c_int { +pub fn _setenv(ctx: ContextMut<'_, EmEnv>, name: c_int, value: c_int, overwrite: c_int) -> c_int { debug!("emscripten::_setenv"); - let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; - let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; + let value_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), value) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); debug!("=> value({:?})", unsafe { CStr::from_ptr(value_addr) }); @@ -43,10 +43,10 @@ pub fn _setenv(ctx: &EmEnv, name: c_int, value: c_int, overwrite: c_int) -> c_in } /// emscripten: _putenv // (name: *const char); -pub fn _putenv(ctx: &EmEnv, name: c_int) -> c_int { +pub fn _putenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { debug!("emscripten::_putenv"); - let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); @@ -54,10 +54,10 @@ pub fn _putenv(ctx: &EmEnv, name: c_int) -> c_int { } /// emscripten: _unsetenv // (name: *const char); -pub fn _unsetenv(ctx: &EmEnv, name: c_int) -> c_int { +pub fn _unsetenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { debug!("emscripten::_unsetenv"); - let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char; + let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) }); @@ -65,7 +65,7 @@ pub fn _unsetenv(ctx: &EmEnv, name: c_int) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getpwnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { +pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { debug!("emscripten::_getpwnam {}", name_ptr); #[cfg(feature = "debug")] let _ = name_ptr; @@ -82,21 +82,25 @@ pub fn _getpwnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { } let name = unsafe { - let memory_name_ptr = emscripten_memory_pointer!(ctx.memory(0), name_ptr) as *const c_char; + let memory = ctx.data().memory(0); + let memory_name_ptr = emscripten_memory_pointer!(ctx, memory, name_ptr) as *const c_char; CStr::from_ptr(memory_name_ptr) }; unsafe { let passwd = &*libc_getpwnam(name.as_ptr()); - let passwd_struct_offset = call_malloc(ctx, mem::size_of::() as _); + let passwd_struct_offset = + call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let memory = ctx.data().memory(0); let passwd_struct_ptr = - emscripten_memory_pointer!(ctx.memory(0), passwd_struct_offset) as *mut GuestPasswd; - (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(ctx, passwd.pw_name); - (*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(ctx, passwd.pw_passwd); - (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(ctx, passwd.pw_gecos); - (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(ctx, passwd.pw_dir); - (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(ctx, passwd.pw_shell); + emscripten_memory_pointer!(ctx, memory, passwd_struct_offset) as *mut GuestPasswd; + (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_name); + (*passwd_struct_ptr).pw_passwd = + copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_passwd); + (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_gecos); + (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_dir); + (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_shell); (*passwd_struct_ptr).pw_uid = passwd.pw_uid; (*passwd_struct_ptr).pw_gid = passwd.pw_gid; @@ -105,7 +109,7 @@ pub fn _getpwnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { +pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { debug!("emscripten::_getgrnam {}", name_ptr); #[repr(C)] @@ -117,18 +121,21 @@ pub fn _getgrnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { } let name = unsafe { - let memory_name_ptr = emscripten_memory_pointer!(ctx.memory(0), name_ptr) as *const c_char; + let memory_name_ptr = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), name_ptr) as *const c_char; CStr::from_ptr(memory_name_ptr) }; unsafe { let group = &*libc_getgrnam(name.as_ptr()); - let group_struct_offset = call_malloc(ctx, mem::size_of::() as _); + let group_struct_offset = + call_malloc(ctx.as_context_mut(), mem::size_of::() as _); let group_struct_ptr = - emscripten_memory_pointer!(ctx.memory(0), group_struct_offset) as *mut GuestGroup; - (*group_struct_ptr).gr_name = copy_cstr_into_wasm(ctx, group.gr_name); - (*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(ctx, group.gr_passwd); + emscripten_memory_pointer!(ctx, ctx.data().memory(0), group_struct_offset) + as *mut GuestGroup; + (*group_struct_ptr).gr_name = copy_cstr_into_wasm(ctx.as_context_mut(), group.gr_name); + (*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(ctx.as_context_mut(), group.gr_passwd); (*group_struct_ptr).gr_gid = group.gr_gid; (*group_struct_ptr).gr_mem = copy_terminated_array_of_cstrs(ctx, group.gr_mem); @@ -136,22 +143,25 @@ pub fn _getgrnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { } } -pub fn _sysconf(_ctx: &EmEnv, name: c_int) -> i32 { +pub fn _sysconf(_ctx: ContextMut<'_, EmEnv>, name: c_int) -> i32 { debug!("emscripten::_sysconf {}", name); // TODO: Implement like emscripten expects regarding memory/page size unsafe { sysconf(name) as i32 } // TODO review i64 } // this may be a memory leak, probably not though because emscripten does the same thing -pub fn _gai_strerror(ctx: &EmEnv, ecode: i32) -> i32 { +pub fn _gai_strerror(mut ctx: ContextMut<'_, EmEnv>, ecode: i32) -> i32 { debug!("emscripten::_gai_strerror({})", ecode); let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) }; let bytes = cstr.to_bytes_with_nul(); - let string_on_guest: WasmPtr = call_malloc_with_cast(ctx, bytes.len() as _); - let memory = ctx.memory(0); + let string_on_guest: WasmPtr = + call_malloc_with_cast(ctx.as_context_mut(), bytes.len() as _); + let memory = ctx.data().memory(0); - let writer = string_on_guest.slice(&memory, bytes.len() as _).unwrap(); + let writer = string_on_guest + .slice(&ctx, &memory, bytes.len() as _) + .unwrap(); for (i, byte) in bytes.iter().enumerate() { writer.index(i as u64).write(*byte as _).unwrap(); } @@ -160,7 +170,7 @@ pub fn _gai_strerror(ctx: &EmEnv, ecode: i32) -> i32 { } pub fn _getaddrinfo( - ctx: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, node_ptr: WasmPtr, service_str_ptr: WasmPtr, hints_ptr: WasmPtr, @@ -168,7 +178,7 @@ pub fn _getaddrinfo( ) -> i32 { use libc::{addrinfo, freeaddrinfo}; debug!("emscripten::_getaddrinfo"); - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); debug!(" => node = {}", { if node_ptr.is_null() { std::borrow::Cow::Borrowed("null") @@ -187,7 +197,7 @@ pub fn _getaddrinfo( let hints = if hints_ptr.is_null() { None } else { - let hints_guest = hints_ptr.deref(&memory).read().unwrap(); + let hints_guest = hints_ptr.deref(&ctx, &memory).read().unwrap(); Some(addrinfo { ai_flags: hints_guest.ai_flags, ai_family: hints_guest.ai_family, @@ -234,14 +244,14 @@ pub fn _getaddrinfo( while !current_host_node.is_null() { let current_guest_node_ptr: WasmPtr = - call_malloc_with_cast(ctx, std::mem::size_of::() as _); + call_malloc_with_cast(ctx.as_context_mut(), std::mem::size_of::() as _); if head_of_list.is_none() { head_of_list = Some(current_guest_node_ptr); } // connect list if let Some(prev_guest) = previous_guest_node { - let derefed_prev_guest = prev_guest.deref(&memory); + let derefed_prev_guest = prev_guest.deref(&ctx, &memory); let mut pg = derefed_prev_guest.read().unwrap(); pg.ai_next = current_guest_node_ptr; derefed_prev_guest.write(pg).unwrap(); @@ -254,9 +264,9 @@ pub fn _getaddrinfo( let guest_sockaddr_ptr = { let host_sockaddr_ptr = (*current_host_node).ai_addr; let guest_sockaddr_ptr: WasmPtr = - call_malloc_with_cast(ctx, host_addrlen as _); + call_malloc_with_cast(ctx.as_context_mut(), host_addrlen as _); - let derefed_guest_sockaddr = guest_sockaddr_ptr.deref(&memory); + let derefed_guest_sockaddr = guest_sockaddr_ptr.deref(&ctx, &memory); let mut gs = derefed_guest_sockaddr.read().unwrap(); gs.sa_family = (*host_sockaddr_ptr).sa_family as i16; gs.sa_data = (*host_sockaddr_ptr).sa_data; @@ -273,10 +283,10 @@ pub fn _getaddrinfo( let canonname_bytes = canonname_cstr.to_bytes_with_nul(); let str_size = canonname_bytes.len(); let guest_canonname: WasmPtr = - call_malloc_with_cast(ctx, str_size as _); + call_malloc_with_cast(ctx.as_context_mut(), str_size as _); let guest_canonname_writer = - guest_canonname.slice(&memory, str_size as _).unwrap(); + guest_canonname.slice(&ctx, &memory, str_size as _).unwrap(); for (i, b) in canonname_bytes.iter().enumerate() { guest_canonname_writer .index(i as u64) @@ -290,7 +300,7 @@ pub fn _getaddrinfo( } }; - let derefed_current_guest_node = current_guest_node_ptr.deref(&memory); + let derefed_current_guest_node = current_guest_node_ptr.deref(&ctx, &memory); let mut cgn = derefed_current_guest_node.read().unwrap(); cgn.ai_flags = (*current_host_node).ai_flags; cgn.ai_family = (*current_host_node).ai_family; @@ -310,7 +320,10 @@ pub fn _getaddrinfo( head_of_list.unwrap_or_else(|| WasmPtr::new(0)) }; - res_val_ptr.deref(&memory).write(head_of_list).unwrap(); + res_val_ptr + .deref(&ctx, &memory) + .write(head_of_list) + .unwrap(); 0 } diff --git a/lib/emscripten/src/errno.rs b/lib/emscripten/src/errno.rs index fcbbe22dfee..fb5681de7c8 100644 --- a/lib/emscripten/src/errno.rs +++ b/lib/emscripten/src/errno.rs @@ -1,7 +1,8 @@ // use std::collections::HashMap; use crate::EmEnv; +use wasmer::ContextMut; -pub fn ___seterrno(_ctx: &EmEnv, _value: i32) { +pub fn ___seterrno(mut _ctx: ContextMut<'_, EmEnv>, _value: i32) { debug!("emscripten::___seterrno {}", _value); // TODO: Incomplete impl eprintln!("failed to set errno!"); diff --git a/lib/emscripten/src/exception.rs b/lib/emscripten/src/exception.rs index 1f781dd652d..c260f1a51d3 100644 --- a/lib/emscripten/src/exception.rs +++ b/lib/emscripten/src/exception.rs @@ -1,56 +1,57 @@ use super::env; use super::process::_abort; use crate::EmEnv; +use wasmer::ContextMut; /// emscripten: ___cxa_allocate_exception -pub fn ___cxa_allocate_exception(ctx: &EmEnv, size: u32) -> u32 { +pub fn ___cxa_allocate_exception(ctx: ContextMut<'_, EmEnv>, size: u32) -> u32 { debug!("emscripten::___cxa_allocate_exception"); env::call_malloc(ctx, size as _) } -pub fn ___cxa_current_primary_exception(_ctx: &EmEnv) -> u32 { +pub fn ___cxa_current_primary_exception(_ctx: ContextMut<'_, EmEnv>) -> u32 { debug!("emscripten::___cxa_current_primary_exception"); unimplemented!("emscripten::___cxa_current_primary_exception") } -pub fn ___cxa_decrement_exception_refcount(_ctx: &EmEnv, _a: u32) { +pub fn ___cxa_decrement_exception_refcount(_ctx: ContextMut<'_, EmEnv>, _a: u32) { debug!("emscripten::___cxa_decrement_exception_refcount({})", _a); unimplemented!("emscripten::___cxa_decrement_exception_refcount({})", _a) } -pub fn ___cxa_increment_exception_refcount(_ctx: &EmEnv, _a: u32) { +pub fn ___cxa_increment_exception_refcount(_ctx: ContextMut<'_, EmEnv>, _a: u32) { debug!("emscripten::___cxa_increment_exception_refcount({})", _a); unimplemented!("emscripten::___cxa_increment_exception_refcount({})", _a) } -pub fn ___cxa_rethrow_primary_exception(_ctx: &EmEnv, _a: u32) { +pub fn ___cxa_rethrow_primary_exception(_ctx: ContextMut<'_, EmEnv>, _a: u32) { debug!("emscripten::___cxa_rethrow_primary_exception({})", _a); unimplemented!("emscripten::___cxa_rethrow_primary_exception({})", _a) } /// emscripten: ___cxa_throw /// TODO: We don't have support for exceptions yet -pub fn ___cxa_throw(ctx: &EmEnv, _ptr: u32, _ty: u32, _destructor: u32) { +pub fn ___cxa_throw(ctx: ContextMut<'_, EmEnv>, _ptr: u32, _ty: u32, _destructor: u32) { debug!("emscripten::___cxa_throw"); eprintln!("Throwing exceptions not yet implemented: aborting!"); _abort(ctx); } -pub fn ___cxa_begin_catch(_ctx: &EmEnv, _exception_object_ptr: u32) -> i32 { +pub fn ___cxa_begin_catch(_ctx: ContextMut<'_, EmEnv>, _exception_object_ptr: u32) -> i32 { debug!("emscripten::___cxa_begin_catch"); -1 } -pub fn ___cxa_end_catch(_ctx: &EmEnv) { +pub fn ___cxa_end_catch(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::___cxa_end_catch"); } -pub fn ___cxa_uncaught_exception(_ctx: &EmEnv) -> i32 { +pub fn ___cxa_uncaught_exception(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::___cxa_uncaught_exception"); -1 } -pub fn ___cxa_pure_virtual(_ctx: &EmEnv) { +pub fn ___cxa_pure_virtual(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::___cxa_pure_virtual"); // ABORT = true panic!("Pure virtual function called!"); diff --git a/lib/emscripten/src/exec.rs b/lib/emscripten/src/exec.rs index 867a3d3115f..2b2485a224d 100644 --- a/lib/emscripten/src/exec.rs +++ b/lib/emscripten/src/exec.rs @@ -3,27 +3,27 @@ use crate::EmEnv; use libc::c_char; use libc::execvp as libc_execvp; use std::ffi::CString; -use wasmer::WasmPtr; +use wasmer::{ContextMut, WasmPtr}; -pub fn execvp(ctx: &EmEnv, command_name_offset: u32, argv_offset: u32) -> i32 { +pub fn execvp(ctx: ContextMut<'_, EmEnv>, command_name_offset: u32, argv_offset: u32) -> i32 { // a single reference to re-use - let emscripten_memory = ctx.memory(0); + let emscripten_memory = ctx.data().memory(0); // read command name as string let command_name_string_vec = WasmPtr::::new(command_name_offset) - .read_until(&emscripten_memory, |&byte| byte == 0) + .read_until(&ctx, &emscripten_memory, |&byte| byte == 0) .unwrap(); let command_name_string = CString::new(command_name_string_vec).unwrap(); // get the array of args let argv = WasmPtr::>::new(argv_offset) - .read_until(&emscripten_memory, |&ptr| ptr.is_null()) + .read_until(&ctx, &emscripten_memory, |&ptr| ptr.is_null()) .unwrap(); let arg_strings: Vec = argv .into_iter() .map(|ptr| { let vec = ptr - .read_until(&emscripten_memory, |&byte| byte == 0) + .read_until(&ctx, &emscripten_memory, |&byte| byte == 0) .unwrap(); CString::new(vec).unwrap() }) @@ -40,13 +40,23 @@ pub fn execvp(ctx: &EmEnv, command_name_offset: u32, argv_offset: u32) -> i32 { } /// execl -pub fn execl(_ctx: &EmEnv, _path_ptr: i32, _arg0_ptr: i32, _varargs: VarArgs) -> i32 { +pub fn execl( + _ctx: ContextMut<'_, EmEnv>, + _path_ptr: i32, + _arg0_ptr: i32, + _varargs: VarArgs, +) -> i32 { debug!("emscripten::execl"); -1 } /// execle -pub fn execle(_ctx: &EmEnv, _path_ptr: i32, _arg0_ptr: i32, _varargs: VarArgs) -> i32 { +pub fn execle( + _ctx: ContextMut<'_, EmEnv>, + _path_ptr: i32, + _arg0_ptr: i32, + _varargs: VarArgs, +) -> i32 { debug!("emscripten::execle"); -1 } diff --git a/lib/emscripten/src/exit.rs b/lib/emscripten/src/exit.rs index 9518d256712..8ef28cceb56 100644 --- a/lib/emscripten/src/exit.rs +++ b/lib/emscripten/src/exit.rs @@ -1,7 +1,8 @@ use crate::EmEnv; +use wasmer::ContextMut; // __exit -pub fn exit(_ctx: &EmEnv, value: i32) { +pub fn exit(mut _ctx: ContextMut<'_, EmEnv>, value: i32) { debug!("emscripten::exit {}", value); ::std::process::exit(value); } diff --git a/lib/emscripten/src/inet.rs b/lib/emscripten/src/inet.rs index ff0267d88a7..b1a59a0feaf 100644 --- a/lib/emscripten/src/inet.rs +++ b/lib/emscripten/src/inet.rs @@ -1,6 +1,7 @@ use crate::EmEnv; +use wasmer::ContextMut; -pub fn addr(_ctx: &EmEnv, _cp: i32) -> i32 { +pub fn addr(mut _ctx: ContextMut<'_, EmEnv>, _cp: i32) -> i32 { debug!("inet::addr({})", _cp); 0 } diff --git a/lib/emscripten/src/io/mod.rs b/lib/emscripten/src/io/mod.rs index 3c0a9d63b66..0971c10d716 100644 --- a/lib/emscripten/src/io/mod.rs +++ b/lib/emscripten/src/io/mod.rs @@ -11,25 +11,26 @@ pub use self::unix::*; pub use self::windows::*; use crate::EmEnv; +use wasmer::ContextMut; /// getprotobyname -pub fn getprotobyname(_ctx: &EmEnv, _name_ptr: i32) -> i32 { +pub fn getprotobyname(_ctx: ContextMut<'_, EmEnv>, _name_ptr: i32) -> i32 { debug!("emscripten::getprotobyname"); unimplemented!("emscripten::getprotobyname") } /// getprotobynumber -pub fn getprotobynumber(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn getprotobynumber(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::getprotobynumber"); unimplemented!("emscripten::getprotobynumber") } /// sigdelset -pub fn sigdelset(ctx: &EmEnv, set: i32, signum: i32) -> i32 { +pub fn sigdelset(ctx: ContextMut<'_, EmEnv>, set: i32, signum: i32) -> i32 { debug!("emscripten::sigdelset"); - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); #[allow(clippy::cast_ptr_alignment)] - let ptr = emscripten_memory_pointer!(memory, set) as *mut i32; + let ptr = emscripten_memory_pointer!(ctx, memory, set) as *mut i32; unsafe { *ptr &= !(1 << (signum - 1)) } @@ -37,11 +38,11 @@ pub fn sigdelset(ctx: &EmEnv, set: i32, signum: i32) -> i32 { } /// sigfillset -pub fn sigfillset(ctx: &EmEnv, set: i32) -> i32 { +pub fn sigfillset(ctx: ContextMut<'_, EmEnv>, set: i32) -> i32 { debug!("emscripten::sigfillset"); - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); #[allow(clippy::cast_ptr_alignment)] - let ptr = emscripten_memory_pointer!(memory, set) as *mut i32; + let ptr = emscripten_memory_pointer!(ctx, memory, set) as *mut i32; unsafe { *ptr = -1; @@ -51,13 +52,13 @@ pub fn sigfillset(ctx: &EmEnv, set: i32) -> i32 { } /// tzset -pub fn tzset(_ctx: &EmEnv) { +pub fn tzset(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::tzset - stub"); //unimplemented!("emscripten::tzset - stub") } /// strptime -pub fn strptime(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn strptime(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::strptime"); unimplemented!("emscripten::strptime") } diff --git a/lib/emscripten/src/io/unix.rs b/lib/emscripten/src/io/unix.rs index 62190653fbf..0e01580778b 100644 --- a/lib/emscripten/src/io/unix.rs +++ b/lib/emscripten/src/io/unix.rs @@ -4,31 +4,32 @@ use libc::{chroot as _chroot, getpwuid as _getpwuid, printf as _printf}; use std::mem; use crate::EmEnv; +use wasmer::{AsContextMut, ContextMut}; /// putchar -pub fn putchar(_ctx: &EmEnv, chr: i32) { +pub fn putchar(_ctx: ContextMut<'_, EmEnv>, chr: i32) { unsafe { libc::putchar(chr) }; } /// printf -pub fn printf(ctx: &EmEnv, memory_offset: i32, extra: i32) -> i32 { +pub fn printf(ctx: ContextMut<'_, EmEnv>, memory_offset: i32, extra: i32) -> i32 { debug!("emscripten::printf {}, {}", memory_offset, extra); unsafe { - let addr = emscripten_memory_pointer!(ctx.memory(0), memory_offset) as _; + let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), memory_offset) as _; _printf(addr, extra) } } /// chroot -pub fn chroot(ctx: &EmEnv, name_ptr: i32) -> i32 { +pub fn chroot(ctx: ContextMut<'_, EmEnv>, name_ptr: i32) -> i32 { debug!("emscripten::chroot"); - let name = emscripten_memory_pointer!(ctx.memory(0), name_ptr) as *const i8; + let name = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name_ptr) as *const i8; unsafe { _chroot(name as *const _) } } /// getpwuid #[allow(clippy::cast_ptr_alignment)] -pub fn getpwuid(ctx: &EmEnv, uid: i32) -> i32 { +pub fn getpwuid(mut ctx: ContextMut<'_, EmEnv>, uid: i32) -> i32 { debug!("emscripten::getpwuid {}", uid); #[repr(C)] @@ -44,18 +45,21 @@ pub fn getpwuid(ctx: &EmEnv, uid: i32) -> i32 { unsafe { let passwd = &*_getpwuid(uid as _); - let passwd_struct_offset = call_malloc(ctx, mem::size_of::() as _); + let passwd_struct_offset = + call_malloc(ctx.as_context_mut(), mem::size_of::() as _); let passwd_struct_ptr = - emscripten_memory_pointer!(ctx.memory(0), passwd_struct_offset) as *mut GuestPasswd; + emscripten_memory_pointer!(ctx, ctx.data().memory(0), passwd_struct_offset) + as *mut GuestPasswd; assert_eq!( passwd_struct_ptr as usize % std::mem::align_of::(), 0 ); - (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(ctx, passwd.pw_name); - (*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(ctx, passwd.pw_passwd); - (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(ctx, passwd.pw_gecos); - (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(ctx, passwd.pw_dir); - (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(ctx, passwd.pw_shell); + (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_name); + (*passwd_struct_ptr).pw_passwd = + copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_passwd); + (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_gecos); + (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_dir); + (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_shell); (*passwd_struct_ptr).pw_uid = passwd.pw_uid; (*passwd_struct_ptr).pw_gid = passwd.pw_gid; diff --git a/lib/emscripten/src/jmp.rs b/lib/emscripten/src/jmp.rs index 93651b1016a..9ac824577cc 100644 --- a/lib/emscripten/src/jmp.rs +++ b/lib/emscripten/src/jmp.rs @@ -1,13 +1,14 @@ -use super::env::get_emscripten_data; +use super::env::get_emscripten_funcs; use super::process::abort_with_message; use libc::c_int; // use std::cell::UnsafeCell; use crate::EmEnv; use std::error::Error; use std::fmt; +use wasmer::{AsContextMut, ContextMut}; /// setjmp -pub fn __setjmp(ctx: &EmEnv, _env_addr: u32) -> c_int { +pub fn __setjmp(ctx: ContextMut<'_, EmEnv>, _env_addr: u32) -> c_int { debug!("emscripten::__setjmp (setjmp)"); abort_with_message(ctx, "missing function: _setjmp"); unreachable!() @@ -18,7 +19,7 @@ pub fn __setjmp(ctx: &EmEnv, _env_addr: u32) -> c_int { // let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8; // // We create the jump buffer outside of the wasm memory // let jump_buf: UnsafeCell<[u32; 27]> = UnsafeCell::new([0; 27]); - // let jumps = &mut get_emscripten_data(ctx).jumps; + // let jumps = &mut get_emscripten_data(&ctx).jumps; // let result = setjmp(jump_buf.get() as _); // // We set the jump index to be the last 3value of jumps // *jump_index = jumps.len() as _; @@ -30,13 +31,13 @@ pub fn __setjmp(ctx: &EmEnv, _env_addr: u32) -> c_int { /// longjmp #[allow(unreachable_code)] -pub fn __longjmp(ctx: &EmEnv, _env_addr: u32, _val: c_int) { +pub fn __longjmp(ctx: ContextMut<'_, EmEnv>, _env_addr: u32, _val: c_int) { debug!("emscripten::__longjmp (longmp)"); abort_with_message(ctx, "missing function: _longjmp"); // unsafe { // // We retrieve the jump index from the env address // let jump_index = emscripten_memory_pointer!(ctx.memory(0), env_addr) as *mut i8; - // let jumps = &mut get_emscripten_data(ctx).jumps; + // let jumps = &mut get_emscripten_data(&ctx).jumps; // // We get the real jump buffer from the jumps vector, using the retrieved index // let jump_buf = &jumps[*jump_index as usize]; // longjmp(jump_buf.get() as _, val) @@ -57,12 +58,18 @@ impl Error for LongJumpRet {} /// _longjmp // This function differs from the js implementation, it should return Result<(), &'static str> #[allow(unreachable_code)] -pub fn _longjmp(ctx: &EmEnv, env_addr: i32, val: c_int) -> Result<(), LongJumpRet> { +pub fn _longjmp( + mut ctx: ContextMut<'_, EmEnv>, + env_addr: i32, + val: c_int, +) -> Result<(), LongJumpRet> { let val = if val == 0 { 1 } else { val }; - get_emscripten_data(ctx) + let threw = get_emscripten_funcs(&ctx) .set_threw_ref() .expect("set_threw is None") - .call(env_addr, val) + .clone(); + threw + .call(&mut ctx.as_context_mut(), env_addr, val) .expect("set_threw failed to call"); Err(LongJumpRet) } diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 294d0c0af22..45befa144f9 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -23,13 +23,16 @@ use std::f64; use std::path::PathBuf; use std::sync::{Arc, Mutex, RwLock}; use wasmer::{ - imports, namespace, ExportError, Exports, Function, FunctionType, Global, Imports, Instance, - LazyInit, Memory, MemoryType, Module, Pages, RuntimeError, Store, Table, TableType, - TypedFunction, Val, ValType, WasmPtr, WasmerEnv, + imports, namespace, AsContextMut, ContextMut, ExportError, Exports, Function, FunctionType, + Global, Imports, Instance, Memory, MemoryType, Module, Pages, RuntimeError, Table, TableType, + TypedFunction, Value, WasmPtr, }; +use wasmer_types::Type as ValType; #[cfg(unix)] -use ::libc::DIR as LibcDir; +extern crate libc as libc_crate; +#[cfg(unix)] +use libc_crate::DIR as LibcDir; // We use a placeholder for windows #[cfg(not(unix))] @@ -76,14 +79,7 @@ pub use self::utils::{ pub struct EmEnv { memory: Arc>>, data: Arc>, -} - -impl WasmerEnv for EmEnv { - fn init_with_instance(&mut self, instance: &Instance) -> Result<(), wasmer::HostEnvInitError> { - let mut ed = self.data.lock().unwrap(); - ed.init_with_instance(instance)?; - Ok(()) - } + funcs: Arc>, } impl EmEnv { @@ -91,6 +87,7 @@ impl EmEnv { Self { memory: Arc::new(RwLock::new(None)), data: Arc::new(Mutex::new(EmscriptenData::new(data.clone(), mapped_dirs))), + funcs: Arc::new(Mutex::new(EmscriptenFunctions::new())), } } @@ -103,6 +100,16 @@ impl EmEnv { pub fn memory(&self, _mem_idx: u32) -> Memory { (&*self.memory.read().unwrap()).as_ref().cloned().unwrap() } + + pub fn set_functions(&mut self, funcs: EmscriptenFunctions) { + self.funcs = Arc::new(Mutex::new(funcs)); + } + + // pub fn init_with_instance(&mut self, instance: &Instance) -> Result<(), wasmer::HostEnvInitError> { + // let mut ed = self.data.lock().unwrap(); + // ed.init_with_instance(instance)?; + // Ok(()) + // } } #[derive(Debug, Clone)] @@ -136,145 +143,92 @@ lazy_static! { const GLOBAL_BASE: u32 = 1024; const STATIC_BASE: u32 = GLOBAL_BASE; -#[derive(WasmerEnv, Clone, Default)] -pub struct EmscriptenData { - pub globals: EmscriptenGlobalsData, - - #[wasmer(export(alias = "_malloc", optional = true))] - pub malloc: LazyInit>, - #[wasmer(export(alias = "_free", optional = true))] - pub free: LazyInit>, - #[wasmer(export(alias = "_memalign", optional = true))] - pub memalign: LazyInit>, - #[wasmer(export(alias = "_memset", optional = true))] - pub memset: LazyInit>, - #[wasmer(export(name = "stackAlloc", optional = true))] - pub stack_alloc: LazyInit>, - pub jumps: Arc>>, - pub opened_dirs: HashMap>, - - #[wasmer(export(name = "dynCall_i", optional = true))] - pub dyn_call_i: LazyInit>, - #[wasmer(export(name = "dynCall_ii", optional = true))] - pub dyn_call_ii: LazyInit>, - #[wasmer(export(name = "dynCall_iii", optional = true))] - pub dyn_call_iii: LazyInit>, - #[wasmer(export(name = "dynCall_iiii", optional = true))] - pub dyn_call_iiii: LazyInit>, - #[wasmer(export(name = "dynCall_iifi", optional = true))] - pub dyn_call_iifi: LazyInit>, - #[wasmer(export(name = "dynCall_v", optional = true))] - pub dyn_call_v: LazyInit>, - #[wasmer(export(name = "dynCall_vi", optional = true))] - pub dyn_call_vi: LazyInit>, - #[wasmer(export(name = "dynCall_vii", optional = true))] - pub dyn_call_vii: LazyInit>, - #[wasmer(export(name = "dynCall_viii", optional = true))] - pub dyn_call_viii: LazyInit>, - #[wasmer(export(name = "dynCall_viiii", optional = true))] - pub dyn_call_viiii: LazyInit>, +#[derive(Clone, Default)] +pub struct EmscriptenFunctions { + pub malloc: Option>, + pub free: Option>, + pub memalign: Option>, + pub memset: Option>, + pub stack_alloc: Option>, + + pub dyn_call_i: Option>, + pub dyn_call_ii: Option>, + pub dyn_call_iii: Option>, + pub dyn_call_iiii: Option>, + pub dyn_call_iifi: Option>, + pub dyn_call_v: Option>, + pub dyn_call_vi: Option>, + pub dyn_call_vii: Option>, + pub dyn_call_viii: Option>, + pub dyn_call_viiii: Option>, // round 2 - #[wasmer(export(name = "dynCall_dii", optional = true))] - pub dyn_call_dii: LazyInit>, - #[wasmer(export(name = "dynCall_diiii", optional = true))] - pub dyn_call_diiii: LazyInit>, - #[wasmer(export(name = "dynCall_iiiii", optional = true))] - pub dyn_call_iiiii: LazyInit>, - #[wasmer(export(name = "dynCall_iiiiii", optional = true))] - pub dyn_call_iiiiii: LazyInit>, - #[wasmer(export(name = "dynCall_iiiiiii", optional = true))] - pub dyn_call_iiiiiii: LazyInit>, - #[wasmer(export(name = "dynCall_iiiiiiii", optional = true))] - pub dyn_call_iiiiiiii: LazyInit>, - #[wasmer(export(name = "dynCall_iiiiiiiii", optional = true))] + pub dyn_call_dii: Option>, + pub dyn_call_diiii: Option>, + pub dyn_call_iiiii: Option>, + pub dyn_call_iiiiii: Option>, + pub dyn_call_iiiiiii: Option>, + pub dyn_call_iiiiiiii: Option>, pub dyn_call_iiiiiiiii: - LazyInit>, - #[wasmer(export(name = "dynCall_iiiiiiiiii", optional = true))] + Option>, pub dyn_call_iiiiiiiiii: - LazyInit>, - #[wasmer(export(name = "dynCall_iiiiiiiiiii", optional = true))] + Option>, pub dyn_call_iiiiiiiiiii: - LazyInit>, - #[wasmer(export(name = "dynCall_vd", optional = true))] - pub dyn_call_vd: LazyInit>, - #[wasmer(export(name = "dynCall_viiiii", optional = true))] - pub dyn_call_viiiii: LazyInit>, - #[wasmer(export(name = "dynCall_viiiiii", optional = true))] - pub dyn_call_viiiiii: LazyInit>, - #[wasmer(export(name = "dynCall_viiiiiii", optional = true))] - pub dyn_call_viiiiiii: LazyInit>, - #[wasmer(export(name = "dynCall_viiiiiiii", optional = true))] - pub dyn_call_viiiiiiii: LazyInit>, - #[wasmer(export(name = "dynCall_viiiiiiiii", optional = true))] + Option>, + pub dyn_call_vd: Option>, + pub dyn_call_viiiii: Option>, + pub dyn_call_viiiiii: Option>, + pub dyn_call_viiiiiii: Option>, + pub dyn_call_viiiiiiii: + Option>, pub dyn_call_viiiiiiiii: - LazyInit>, - #[wasmer(export(name = "dynCall_viiiiiiiiii", optional = true))] + Option>, pub dyn_call_viiiiiiiiii: - LazyInit>, - #[wasmer(export(name = "dynCall_iij", optional = true))] - pub dyn_call_iij: LazyInit>, - #[wasmer(export(name = "dynCall_iji", optional = true))] - pub dyn_call_iji: LazyInit>, - #[wasmer(export(name = "dynCall_iiji", optional = true))] - pub dyn_call_iiji: LazyInit>, - #[wasmer(export(name = "dynCall_iiijj", optional = true))] - pub dyn_call_iiijj: LazyInit>, - #[wasmer(export(name = "dynCall_j", optional = true))] - pub dyn_call_j: LazyInit>, - #[wasmer(export(name = "dynCall_ji", optional = true))] - pub dyn_call_ji: LazyInit>, - #[wasmer(export(name = "dynCall_jii", optional = true))] - pub dyn_call_jii: LazyInit>, - #[wasmer(export(name = "dynCall_jij", optional = true))] - pub dyn_call_jij: LazyInit>, - #[wasmer(export(name = "dynCall_jjj", optional = true))] - pub dyn_call_jjj: LazyInit>, - #[wasmer(export(name = "dynCall_viiij", optional = true))] - pub dyn_call_viiij: LazyInit>, - #[wasmer(export(name = "dynCall_viiijiiii", optional = true))] + Option>, + pub dyn_call_iij: Option>, + pub dyn_call_iji: Option>, + pub dyn_call_iiji: Option>, + pub dyn_call_iiijj: Option>, + pub dyn_call_j: Option>, + pub dyn_call_ji: Option>, + pub dyn_call_jii: Option>, + pub dyn_call_jij: Option>, + pub dyn_call_jjj: Option>, + pub dyn_call_viiij: Option>, pub dyn_call_viiijiiii: - LazyInit>, - #[wasmer(export(name = "dynCall_viiijiiiiii", optional = true))] + Option>, pub dyn_call_viiijiiiiii: - LazyInit>, - #[wasmer(export(name = "dynCall_viij", optional = true))] - pub dyn_call_viij: LazyInit>, - #[wasmer(export(name = "dynCall_viiji", optional = true))] - pub dyn_call_viiji: LazyInit>, - #[wasmer(export(name = "dynCall_viijiii", optional = true))] - pub dyn_call_viijiii: LazyInit>, - #[wasmer(export(name = "dynCall_viijj", optional = true))] - pub dyn_call_viijj: LazyInit>, - #[wasmer(export(name = "dynCall_vj", optional = true))] - pub dyn_call_vj: LazyInit>, - #[wasmer(export(name = "dynCall_vjji", optional = true))] - pub dyn_call_vjji: LazyInit>, - #[wasmer(export(name = "dynCall_vij", optional = true))] - pub dyn_call_vij: LazyInit>, - #[wasmer(export(name = "dynCall_viji", optional = true))] - pub dyn_call_viji: LazyInit>, - #[wasmer(export(name = "dynCall_vijiii", optional = true))] - pub dyn_call_vijiii: LazyInit>, - #[wasmer(export(name = "dynCall_vijj", optional = true))] - pub dyn_call_vijj: LazyInit>, - #[wasmer(export(name = "dynCall_viid", optional = true))] - pub dyn_call_viid: LazyInit>, - #[wasmer(export(name = "dynCall_vidd", optional = true))] - pub dyn_call_vidd: LazyInit>, - #[wasmer(export(name = "dynCall_viidii", optional = true))] - pub dyn_call_viidii: LazyInit>, - #[wasmer(export(name = "dynCall_viidddddddd", optional = true))] + Option>, + pub dyn_call_viij: Option>, + pub dyn_call_viiji: Option>, + pub dyn_call_viijiii: Option>, + pub dyn_call_viijj: Option>, + pub dyn_call_vj: Option>, + pub dyn_call_vjji: Option>, + pub dyn_call_vij: Option>, + pub dyn_call_viji: Option>, + pub dyn_call_vijiii: Option>, + pub dyn_call_vijj: Option>, + pub dyn_call_viid: Option>, + pub dyn_call_vidd: Option>, + pub dyn_call_viidii: Option>, pub dyn_call_viidddddddd: - LazyInit>, + Option>, + + pub stack_save: Option>, + pub stack_restore: Option>, + pub set_threw: Option>, +} + +#[derive(Clone, Default)] +pub struct EmscriptenData { + pub globals: EmscriptenGlobalsData, + + pub jumps: Arc>>, + pub opened_dirs: HashMap>, + pub temp_ret_0: i32, - #[wasmer(export(name = "stackSave", optional = true))] - pub stack_save: LazyInit>, - #[wasmer(export(name = "stackRestore", optional = true))] - pub stack_restore: LazyInit>, - #[wasmer(export(name = "setThrew", alias = "_setThrew", optional = true))] - pub set_threw: LazyInit>, pub mapped_dirs: HashMap, } @@ -292,23 +246,257 @@ impl EmscriptenData { } } +impl EmscriptenFunctions { + pub fn new() -> EmscriptenFunctions { + EmscriptenFunctions { + ..Default::default() + } + } + pub fn malloc_ref(&self) -> Option<&TypedFunction> { + self.malloc.as_ref() + } + pub fn free_ref(&self) -> Option<&TypedFunction> { + self.free.as_ref() + } + pub fn memalign_ref(&self) -> Option<&TypedFunction<(u32, u32), u32>> { + self.memalign.as_ref() + } + pub fn memset_ref(&self) -> Option<&TypedFunction<(u32, u32, u32), u32>> { + self.memset.as_ref() + } + pub fn stack_alloc_ref(&self) -> Option<&TypedFunction> { + self.stack_alloc.as_ref() + } + + pub fn dyn_call_i_ref(&self) -> Option<&TypedFunction> { + self.dyn_call_i.as_ref() + } + pub fn dyn_call_ii_ref(&self) -> Option<&TypedFunction<(i32, i32), i32>> { + self.dyn_call_ii.as_ref() + } + pub fn dyn_call_iii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32), i32>> { + self.dyn_call_iii.as_ref() + } + pub fn dyn_call_iiii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32), i32>> { + self.dyn_call_iiii.as_ref() + } + pub fn dyn_call_iifi_ref(&self) -> Option<&TypedFunction<(i32, i32, f64, i32), i32>> { + self.dyn_call_iifi.as_ref() + } + pub fn dyn_call_v_ref(&self) -> Option<&TypedFunction> { + self.dyn_call_v.as_ref() + } + pub fn dyn_call_vi_ref(&self) -> Option<&TypedFunction<(i32, i32), ()>> { + self.dyn_call_vi.as_ref() + } + pub fn dyn_call_vii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32), ()>> { + self.dyn_call_vii.as_ref() + } + pub fn dyn_call_viii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32), ()>> { + self.dyn_call_viii.as_ref() + } + pub fn dyn_call_viiii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiii.as_ref() + } + pub fn dyn_call_dii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32), f64>> { + self.dyn_call_dii.as_ref() + } + pub fn dyn_call_diiii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32), f64>> { + self.dyn_call_diiii.as_ref() + } + pub fn dyn_call_iiiii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiiii.as_ref() + } + pub fn dyn_call_iiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiiiii.as_ref() + } + pub fn dyn_call_iiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiiiiii.as_ref() + } + pub fn dyn_call_iiiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiiiiiii.as_ref() + } + pub fn dyn_call_iiiiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiiiiiiii.as_ref() + } + pub fn dyn_call_iiiiiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiiiiiiiii.as_ref() + } + pub fn dyn_call_iiiiiiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiiiiiiiiii.as_ref() + } + pub fn dyn_call_vd_ref(&self) -> Option<&TypedFunction<(i32, f64), ()>> { + self.dyn_call_vd.as_ref() + } + pub fn dyn_call_viiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiiii.as_ref() + } + pub fn dyn_call_viiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiiiii.as_ref() + } + pub fn dyn_call_viiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiiiiii.as_ref() + } + pub fn dyn_call_viiiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiiiiiii.as_ref() + } + pub fn dyn_call_viiiiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiiiiiiii.as_ref() + } + pub fn dyn_call_viiiiiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiiiiiiiii.as_ref() + } + pub fn dyn_call_iij_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32), i32>> { + self.dyn_call_iij.as_ref() + } + pub fn dyn_call_iji_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32), i32>> { + self.dyn_call_iji.as_ref() + } + pub fn dyn_call_iiji_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiji.as_ref() + } + pub fn dyn_call_iiijj_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32), i32>> { + self.dyn_call_iiijj.as_ref() + } + pub fn dyn_call_j_ref(&self) -> Option<&TypedFunction> { + self.dyn_call_j.as_ref() + } + pub fn dyn_call_ji_ref(&self) -> Option<&TypedFunction<(i32, i32), i32>> { + self.dyn_call_ji.as_ref() + } + pub fn dyn_call_jii_ref(&self) -> Option<&TypedFunction<(i32, i32, i32), i32>> { + self.dyn_call_jii.as_ref() + } + pub fn dyn_call_jij_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32), i32>> { + self.dyn_call_jij.as_ref() + } + pub fn dyn_call_jjj_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32), i32>> { + self.dyn_call_jjj.as_ref() + } + pub fn dyn_call_viiij_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiij.as_ref() + } + pub fn dyn_call_viiijiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiijiiii.as_ref() + } + pub fn dyn_call_viiijiiiiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>> + { + self.dyn_call_viiijiiiiii.as_ref() + } + pub fn dyn_call_viij_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viij.as_ref() + } + pub fn dyn_call_viiji_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viiji.as_ref() + } + pub fn dyn_call_viijiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viijiii.as_ref() + } + pub fn dyn_call_viijj_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viijj.as_ref() + } + pub fn dyn_call_vj_ref(&self) -> Option<&TypedFunction<(i32, i32, i32), ()>> { + self.dyn_call_vj.as_ref() + } + pub fn dyn_call_vjji_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_vjji.as_ref() + } + pub fn dyn_call_vij_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32), ()>> { + self.dyn_call_vij.as_ref() + } + pub fn dyn_call_viji_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32), ()>> { + self.dyn_call_viji.as_ref() + } + pub fn dyn_call_vijiii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_vijiii.as_ref() + } + pub fn dyn_call_vijj_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, i32, i32, i32), ()>> { + self.dyn_call_vijj.as_ref() + } + pub fn dyn_call_viid_ref(&self) -> Option<&TypedFunction<(i32, i32, i32, f64), ()>> { + self.dyn_call_viid.as_ref() + } + pub fn dyn_call_vidd_ref(&self) -> Option<&TypedFunction<(i32, i32, f64, f64), ()>> { + self.dyn_call_vidd.as_ref() + } + pub fn dyn_call_viidii_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, f64, i32, i32), ()>> { + self.dyn_call_viidii.as_ref() + } + pub fn dyn_call_viidddddddd_ref( + &self, + ) -> Option<&TypedFunction<(i32, i32, i32, f64, f64, f64, f64, f64, f64, f64, f64), ()>> { + self.dyn_call_viidddddddd.as_ref() + } + + pub fn stack_save_ref(&self) -> Option<&TypedFunction<(), i32>> { + self.stack_save.as_ref() + } + pub fn stack_restore_ref(&self) -> Option<&TypedFunction> { + self.stack_restore.as_ref() + } + pub fn set_threw_ref(&self) -> Option<&TypedFunction<(i32, i32), ()>> { + self.set_threw.as_ref() + } +} + /// Call the global constructors for C++ and set up the emscripten environment. /// /// Note that this function does not completely set up Emscripten to be called. /// before calling this function, please initialize `Ctx::data` with a pointer /// to [`EmscriptenData`]. -pub fn set_up_emscripten(instance: &mut Instance) -> Result<(), RuntimeError> { +pub fn set_up_emscripten( + ctx: &mut ContextMut<'_, EmEnv>, + instance: &mut Instance, +) -> Result<(), RuntimeError> { // ATINIT // (used by C++) - if let Ok(func) = instance.exports.get::("globalCtors") { - func.call(&[])?; + if let Ok(func) = instance.exports.get_function("globalCtors") { + func.call(&mut ctx.as_context_mut(), &[])?; } if let Ok(func) = instance .exports - .get::("___emscripten_environ_constructor") + .get_function("___emscripten_environ_constructor") { - func.call(&[])?; + func.call(&mut ctx.as_context_mut(), &[])?; } Ok(()) } @@ -350,7 +538,7 @@ pub fn emscripten_get_main_func_name<'a>( pub fn emscripten_call_main( instance: &mut Instance, function_name: &str, - env: &EmEnv, + mut ctx: ContextMut<'_, EmEnv>, path: &str, args: &[&str], ) -> Result<(), RuntimeError> { @@ -358,24 +546,27 @@ pub fn emscripten_call_main( .exports .get::(function_name) .map_err(|e| RuntimeError::new(e.to_string()))?; - let num_params = main_func.ty().params().len(); + let num_params = main_func.ty(&ctx).params().len(); let _result = match num_params { 2 => { let mut new_args = vec![path]; new_args.extend(args); - let (argc, argv) = store_module_arguments(env, new_args); + let (argc, argv) = store_module_arguments(ctx.as_context_mut(), new_args); let func: &Function = instance .exports .get(function_name) .map_err(|e| RuntimeError::new(e.to_string()))?; - func.call(&[Val::I32(argc as i32), Val::I32(argv as i32)])?; + func.call( + &mut ctx, + &[Value::I32(argc as i32), Value::I32(argv as i32)], + )?; } 0 => { let func: &Function = instance .exports .get(function_name) .map_err(|e| RuntimeError::new(e.to_string()))?; - func.call(&[])?; + func.call(&mut ctx, &[])?; } _ => { todo!("Update error type to be able to express this"); @@ -391,21 +582,256 @@ pub fn emscripten_call_main( /// Top level function to execute emscripten pub fn run_emscripten_instance( instance: &mut Instance, - env: &mut EmEnv, + mut ctx: ContextMut<'_, EmEnv>, globals: &mut EmscriptenGlobals, path: &str, args: Vec<&str>, entrypoint: Option, ) -> Result<(), RuntimeError> { + let env = &mut ctx.data_mut(); env.set_memory(globals.memory.clone()); - set_up_emscripten(instance)?; + // get emscripten export + let mut emfuncs = EmscriptenFunctions::new(); + if let Ok(func) = instance.exports.get_native_function(&ctx, "malloc") { + emfuncs.malloc = Some(func); + } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_malloc") { + emfuncs.malloc = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "free") { + emfuncs.free = Some(func); + } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_free") { + emfuncs.free = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "memalign") { + emfuncs.memalign = Some(func); + } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_memalign") { + emfuncs.memalign = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "memset") { + emfuncs.memset = Some(func); + } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_memset") { + emfuncs.memset = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "stackAlloc") { + emfuncs.stack_alloc = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_i") { + emfuncs.dyn_call_i = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_ii") { + emfuncs.dyn_call_ii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iii") { + emfuncs.dyn_call_iii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiii") { + emfuncs.dyn_call_iiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iifi") { + emfuncs.dyn_call_iifi = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_v") { + emfuncs.dyn_call_v = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vi") { + emfuncs.dyn_call_vi = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vii") { + emfuncs.dyn_call_vii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viii") { + emfuncs.dyn_call_viii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiii") { + emfuncs.dyn_call_viiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_dii") { + emfuncs.dyn_call_dii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_diiii") { + emfuncs.dyn_call_diiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiiii") { + emfuncs.dyn_call_iiiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiiiii") { + emfuncs.dyn_call_iiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_iiiiiii") + { + emfuncs.dyn_call_iiiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_iiiiiiii") + { + emfuncs.dyn_call_iiiiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_iiiiiiiii") + { + emfuncs.dyn_call_iiiiiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_iiiiiiiiii") + { + emfuncs.dyn_call_iiiiiiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_iiiiiiiiiii") + { + emfuncs.dyn_call_iiiiiiiiiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vd") { + emfuncs.dyn_call_vd = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiiii") { + emfuncs.dyn_call_viiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viiiiii") + { + emfuncs.dyn_call_viiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viiiiiii") + { + emfuncs.dyn_call_viiiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viiiiiiii") + { + emfuncs.dyn_call_viiiiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viiiiiiiii") + { + emfuncs.dyn_call_viiiiiiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viiiiiiiiii") + { + emfuncs.dyn_call_viiiiiiiiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iij") { + emfuncs.dyn_call_iij = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iji") { + emfuncs.dyn_call_iji = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiji") { + emfuncs.dyn_call_iiji = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiijj") { + emfuncs.dyn_call_iiijj = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_j") { + emfuncs.dyn_call_j = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_ji") { + emfuncs.dyn_call_ji = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_jii") { + emfuncs.dyn_call_jii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_jij") { + emfuncs.dyn_call_jij = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_jjj") { + emfuncs.dyn_call_jjj = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiij") { + emfuncs.dyn_call_viiij = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viiijiiii") + { + emfuncs.dyn_call_viiijiiii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viiijiiiiii") + { + emfuncs.dyn_call_viiijiiiiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viij") { + emfuncs.dyn_call_viij = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiji") { + emfuncs.dyn_call_viiji = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viijiii") + { + emfuncs.dyn_call_viijiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viijj") { + emfuncs.dyn_call_viijj = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vj") { + emfuncs.dyn_call_vj = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vjji") { + emfuncs.dyn_call_vjji = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vij") { + emfuncs.dyn_call_vij = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viji") { + emfuncs.dyn_call_viji = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vijiii") { + emfuncs.dyn_call_vijiii = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vijj") { + emfuncs.dyn_call_vijj = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viid") { + emfuncs.dyn_call_viid = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vidd") { + emfuncs.dyn_call_vidd = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viidii") { + emfuncs.dyn_call_viidii = Some(func); + } + if let Ok(func) = instance + .exports + .get_native_function(&ctx, "dynCall_viidddddddd") + { + emfuncs.dyn_call_viidddddddd = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "stackSave") { + emfuncs.stack_save = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "stackRestore") { + emfuncs.stack_restore = Some(func); + } + if let Ok(func) = instance.exports.get_native_function(&ctx, "setThrew") { + emfuncs.set_threw = Some(func); + } + ctx.data_mut().set_functions(emfuncs); + + set_up_emscripten(&mut ctx.as_context_mut(), instance)?; let main_func_names = ["_main", "main"]; if let Some(ep) = entrypoint.as_ref() { debug!("Running entry point: {}", ep); - emscripten_call_main(instance, ep, env, path, &args)?; + emscripten_call_main(instance, ep, ctx, path, &args)?; } else if let Ok(name) = emscripten_get_main_func_name(instance, &main_func_names) { - emscripten_call_main(instance, name, env, path, &args)?; + emscripten_call_main(instance, name, ctx, path, &args)?; } else { return Err(RuntimeError::new(format!( "No main function found (searched: {main_func_names:?}) and no entrypoint specified" @@ -417,16 +843,16 @@ pub fn run_emscripten_instance( Ok(()) } -fn store_module_arguments(ctx: &EmEnv, args: Vec<&str>) -> (u32, u32) { +fn store_module_arguments(mut ctx: ContextMut<'_, EmEnv>, args: Vec<&str>) -> (u32, u32) { let argc = args.len() + 1; let mut args_slice = vec![0; argc]; for (slot, arg) in args_slice[0..argc].iter_mut().zip(args.iter()) { - *slot = unsafe { allocate_cstr_on_stack(ctx, arg).0 }; + *slot = unsafe { allocate_cstr_on_stack(&mut ctx.as_context_mut(), arg).0 }; } let (argv_offset, argv_slice): (_, &mut [u32]) = - unsafe { allocate_on_stack(ctx, ((argc) * 4) as u32) }; + unsafe { allocate_on_stack(&mut ctx, ((argc) * 4) as u32) }; assert!(!argv_slice.is_empty()); for (slot, arg) in argv_slice[0..argc].iter_mut().zip(args_slice.iter()) { *slot = *arg @@ -437,13 +863,15 @@ fn store_module_arguments(ctx: &EmEnv, args: Vec<&str>) -> (u32, u32) { } pub fn emscripten_set_up_memory( + mut ctx: ContextMut<'_, EmEnv>, memory: &Memory, globals: &EmscriptenGlobalsData, ) -> Result<(), String> { - let dynamictop_ptr = WasmPtr::::new(globals.dynamictop_ptr).deref(memory); + ctx.data_mut().set_memory(memory.clone()); + let dynamictop_ptr = WasmPtr::::new(globals.dynamictop_ptr).deref(&ctx, memory); let dynamic_base = globals.dynamic_base; - if dynamictop_ptr.offset() >= memory.data_size() { + if dynamictop_ptr.offset() >= memory.data_size(&ctx) { return Err("dynamictop_ptr beyond memory len".to_string()); } dynamictop_ptr.write(dynamic_base as i32).unwrap(); @@ -477,7 +905,7 @@ pub struct EmscriptenGlobals { impl EmscriptenGlobals { pub fn new( - store: &Store, + mut ctx: ContextMut<'_, EmEnv>, module: &Module, /*, static_bump: u32 */ ) -> Result { let mut use_old_abort_on_cannot_grow_memory = false; @@ -495,14 +923,14 @@ impl EmscriptenGlobals { // Memory initialization let memory_type = MemoryType::new(memory_min, memory_max, shared); - let memory = Memory::new(store, memory_type).unwrap(); + let memory = Memory::new(&mut ctx, memory_type).unwrap(); let table_type = TableType { ty: ValType::FuncRef, minimum: table_min, maximum: table_max, }; - let table = Table::new(store, table_type, Val::FuncRef(None)).unwrap(); + let table = Table::new(&mut ctx, table_type, Value::FuncRef(None)).unwrap(); let data = { let static_bump = STATIC_BUMP; @@ -540,7 +968,7 @@ impl EmscriptenGlobals { } }; - emscripten_set_up_memory(&memory, &data)?; + emscripten_set_up_memory(ctx, &memory, &data)?; let mut null_function_names = vec![]; for import in module.imports().functions() { @@ -564,22 +992,13 @@ impl EmscriptenGlobals { } pub fn generate_emscripten_env( - store: &Store, + ctx: &mut ContextMut<'_, EmEnv>, globals: &mut EmscriptenGlobals, - env: &EmEnv, ) -> Imports { let abort_on_cannot_grow_memory_export = if globals.data.use_old_abort_on_cannot_grow_memory { - Function::new_native_with_env( - store, - env.clone(), - crate::memory::abort_on_cannot_grow_memory_old, - ) + Function::new_native(ctx, crate::memory::abort_on_cannot_grow_memory_old) } else { - Function::new_native_with_env( - store, - env.clone(), - crate::memory::abort_on_cannot_grow_memory, - ) + Function::new_native(ctx, crate::memory::abort_on_cannot_grow_memory) }; let mut env_ns: Exports = namespace! { @@ -587,440 +1006,440 @@ pub fn generate_emscripten_env( "table" => globals.table.clone(), // Globals - "STACKTOP" => Global::new(store, Val::I32(globals.data.stacktop as i32)), - "STACK_MAX" => Global::new(store, Val::I32(globals.data.stack_max as i32)), - "DYNAMICTOP_PTR" => Global::new(store, Val::I32(globals.data.dynamictop_ptr as i32)), - "fb" => Global::new(store, Val::I32(globals.data.table_base as i32)), - "tableBase" => Global::new(store, Val::I32(globals.data.table_base as i32)), - "__table_base" => Global::new(store, Val::I32(globals.data.table_base as i32)), - "ABORT" => Global::new(store, Val::I32(globals.data.abort as i32)), - "gb" => Global::new(store, Val::I32(globals.data.memory_base as i32)), - "memoryBase" => Global::new(store, Val::I32(globals.data.memory_base as i32)), - "__memory_base" => Global::new(store, Val::I32(globals.data.memory_base as i32)), - "tempDoublePtr" => Global::new(store, Val::I32(globals.data.temp_double_ptr as i32)), + "STACKTOP" => Global::new(ctx, Value::I32(globals.data.stacktop as i32)), + "STACK_MAX" => Global::new(ctx, Value::I32(globals.data.stack_max as i32)), + "DYNAMICTOP_PTR" => Global::new(ctx, Value::I32(globals.data.dynamictop_ptr as i32)), + "fb" => Global::new(ctx, Value::I32(globals.data.table_base as i32)), + "tableBase" => Global::new(ctx, Value::I32(globals.data.table_base as i32)), + "__table_base" => Global::new(ctx, Value::I32(globals.data.table_base as i32)), + "ABORT" => Global::new(ctx, Value::I32(globals.data.abort as i32)), + "gb" => Global::new(ctx, Value::I32(globals.data.memory_base as i32)), + "memoryBase" => Global::new(ctx, Value::I32(globals.data.memory_base as i32)), + "__memory_base" => Global::new(ctx, Value::I32(globals.data.memory_base as i32)), + "tempDoublePtr" => Global::new(ctx, Value::I32(globals.data.temp_double_ptr as i32)), // inet - "_inet_addr" => Function::new_native_with_env(store, env.clone(), crate::inet::addr), + "_inet_addr" => Function::new_native(ctx, crate::inet::addr), // IO - "printf" => Function::new_native_with_env(store, env.clone(), crate::io::printf), - "putchar" => Function::new_native_with_env(store, env.clone(), crate::io::putchar), - "___lock" => Function::new_native_with_env(store, env.clone(), crate::lock::___lock), - "___unlock" => Function::new_native_with_env(store, env.clone(), crate::lock::___unlock), - "___wait" => Function::new_native_with_env(store, env.clone(), crate::lock::___wait), - "_flock" => Function::new_native_with_env(store, env.clone(), crate::lock::_flock), - "_chroot" => Function::new_native_with_env(store, env.clone(), crate::io::chroot), - "_getprotobyname" => Function::new_native_with_env(store, env.clone(), crate::io::getprotobyname), - "_getprotobynumber" => Function::new_native_with_env(store, env.clone(), crate::io::getprotobynumber), - "_getpwuid" => Function::new_native_with_env(store, env.clone(), crate::io::getpwuid), - "_sigdelset" => Function::new_native_with_env(store, env.clone(), crate::io::sigdelset), - "_sigfillset" => Function::new_native_with_env(store, env.clone(), crate::io::sigfillset), - "_tzset" => Function::new_native_with_env(store, env.clone(), crate::io::tzset), - "_strptime" => Function::new_native_with_env(store, env.clone(), crate::io::strptime), + "printf" => Function::new_native(ctx, crate::io::printf), + "putchar" => Function::new_native(ctx, crate::io::putchar), + "___lock" => Function::new_native(ctx, crate::lock::___lock), + "___unlock" => Function::new_native(ctx, crate::lock::___unlock), + "___wait" => Function::new_native(ctx, crate::lock::___wait), + "_flock" => Function::new_native(ctx, crate::lock::_flock), + "_chroot" => Function::new_native(ctx, crate::io::chroot), + "_getprotobyname" => Function::new_native(ctx, crate::io::getprotobyname), + "_getprotobynumber" => Function::new_native(ctx, crate::io::getprotobynumber), + "_getpwuid" => Function::new_native(ctx, crate::io::getpwuid), + "_sigdelset" => Function::new_native(ctx, crate::io::sigdelset), + "_sigfillset" => Function::new_native(ctx, crate::io::sigfillset), + "_tzset" => Function::new_native(ctx, crate::io::tzset), + "_strptime" => Function::new_native(ctx, crate::io::strptime), // exec - "_execvp" => Function::new_native_with_env(store, env.clone(), crate::exec::execvp), - "_execl" => Function::new_native_with_env(store, env.clone(), crate::exec::execl), - "_execle" => Function::new_native_with_env(store, env.clone(), crate::exec::execle), + "_execvp" => Function::new_native(ctx, crate::exec::execvp), + "_execl" => Function::new_native(ctx, crate::exec::execl), + "_execle" => Function::new_native(ctx, crate::exec::execle), // exit - "__exit" => Function::new_native_with_env(store, env.clone(), crate::exit::exit), + "__exit" => Function::new_native(ctx, crate::exit::exit), // Env - "___assert_fail" => Function::new_native_with_env(store, env.clone(), crate::env::___assert_fail), - "_getenv" => Function::new_native_with_env(store, env.clone(), crate::env::_getenv), - "_setenv" => Function::new_native_with_env(store, env.clone(), crate::env::_setenv), - "_putenv" => Function::new_native_with_env(store, env.clone(), crate::env::_putenv), - "_unsetenv" => Function::new_native_with_env(store, env.clone(), crate::env::_unsetenv), - "_getpwnam" => Function::new_native_with_env(store, env.clone(), crate::env::_getpwnam), - "_getgrnam" => Function::new_native_with_env(store, env.clone(), crate::env::_getgrnam), - "___buildEnvironment" => Function::new_native_with_env(store, env.clone(), crate::env::___build_environment), - "___setErrNo" => Function::new_native_with_env(store, env.clone(), crate::errno::___seterrno), - "_getpagesize" => Function::new_native_with_env(store, env.clone(), crate::env::_getpagesize), - "_sysconf" => Function::new_native_with_env(store, env.clone(), crate::env::_sysconf), - "_getaddrinfo" => Function::new_native_with_env(store, env.clone(), crate::env::_getaddrinfo), - "_times" => Function::new_native_with_env(store, env.clone(), crate::env::_times), - "_pathconf" => Function::new_native_with_env(store, env.clone(), crate::env::_pathconf), - "_fpathconf" => Function::new_native_with_env(store, env.clone(), crate::env::_fpathconf), + "___assert_fail" => Function::new_native(ctx, crate::env::___assert_fail), + "_getenv" => Function::new_native(ctx, crate::env::_getenv), + "_setenv" => Function::new_native(ctx, crate::env::_setenv), + "_putenv" => Function::new_native(ctx, crate::env::_putenv), + "_unsetenv" => Function::new_native(ctx, crate::env::_unsetenv), + "_getpwnam" => Function::new_native(ctx, crate::env::_getpwnam), + "_getgrnam" => Function::new_native(ctx, crate::env::_getgrnam), + "___buildEnvironment" => Function::new_native(ctx, crate::env::___build_environment), + "___setErrNo" => Function::new_native(ctx, crate::errno::___seterrno), + "_getpagesize" => Function::new_native(ctx, crate::env::_getpagesize), + "_sysconf" => Function::new_native(ctx, crate::env::_sysconf), + "_getaddrinfo" => Function::new_native(ctx, crate::env::_getaddrinfo), + "_times" => Function::new_native(ctx, crate::env::_times), + "_pathconf" => Function::new_native(ctx, crate::env::_pathconf), + "_fpathconf" => Function::new_native(ctx, crate::env::_fpathconf), // Syscalls - "___syscall1" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall1), - "___syscall3" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall3), - "___syscall4" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall4), - "___syscall5" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall5), - "___syscall6" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall6), - "___syscall9" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall9), - "___syscall10" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall10), - "___syscall12" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall12), - "___syscall14" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall14), - "___syscall15" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall15), - "___syscall20" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall20), - "___syscall21" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall21), - "___syscall25" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall25), - "___syscall29" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall29), - "___syscall32" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall32), - "___syscall33" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall33), - "___syscall34" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall34), - "___syscall36" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall36), - "___syscall39" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall39), - "___syscall38" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall38), - "___syscall40" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall40), - "___syscall41" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall41), - "___syscall42" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall42), - "___syscall51" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall51), - "___syscall52" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall52), - "___syscall53" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall53), - "___syscall54" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall54), - "___syscall57" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall57), - "___syscall60" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall60), - "___syscall63" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall63), - "___syscall64" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall64), - "___syscall66" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall66), - "___syscall75" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall75), - "___syscall77" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall77), - "___syscall83" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall83), - "___syscall85" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall85), - "___syscall91" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall91), - "___syscall94" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall94), - "___syscall96" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall96), - "___syscall97" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall97), - "___syscall102" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall102), - "___syscall110" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall110), - "___syscall114" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall114), - "___syscall118" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall118), - "___syscall121" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall121), - "___syscall122" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall122), - "___syscall125" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall125), - "___syscall132" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall132), - "___syscall133" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall133), - "___syscall140" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall140), - "___syscall142" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall142), - "___syscall144" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall144), - "___syscall145" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall145), - "___syscall146" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall146), - "___syscall147" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall147), - "___syscall148" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall148), - "___syscall150" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall150), - "___syscall151" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall151), - "___syscall152" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall152), - "___syscall153" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall153), - "___syscall163" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall163), - "___syscall168" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall168), - "___syscall180" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall180), - "___syscall181" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall181), - "___syscall183" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall183), - "___syscall191" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall191), - "___syscall192" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall192), - "___syscall193" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall193), - "___syscall194" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall194), - "___syscall195" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall195), - "___syscall196" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall196), - "___syscall197" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall197), - "___syscall198" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall198), - "___syscall199" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall199), - "___syscall200" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall200), - "___syscall201" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall201), - "___syscall202" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall202), - "___syscall205" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall205), - "___syscall207" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall207), - "___syscall209" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall209), - "___syscall211" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall211), - "___syscall212" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall212), - "___syscall218" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall218), - "___syscall219" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall219), - "___syscall220" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall220), - "___syscall221" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall221), - "___syscall268" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall268), - "___syscall269" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall269), - "___syscall272" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall272), - "___syscall295" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall295), - "___syscall296" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall296), - "___syscall297" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall297), - "___syscall298" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall298), - "___syscall300" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall300), - "___syscall301" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall301), - "___syscall302" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall302), - "___syscall303" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall303), - "___syscall304" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall304), - "___syscall305" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall305), - "___syscall306" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall306), - "___syscall307" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall307), - "___syscall308" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall308), - "___syscall320" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall320), - "___syscall324" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall324), - "___syscall330" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall330), - "___syscall331" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall331), - "___syscall333" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall333), - "___syscall334" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall334), - "___syscall337" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall337), - "___syscall340" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall340), - "___syscall345" => Function::new_native_with_env(store, env.clone(), crate::syscalls::___syscall345), + "___syscall1" => Function::new_native(ctx, crate::syscalls::___syscall1), + "___syscall3" => Function::new_native(ctx, crate::syscalls::___syscall3), + "___syscall4" => Function::new_native(ctx, crate::syscalls::___syscall4), + "___syscall5" => Function::new_native(ctx, crate::syscalls::___syscall5), + "___syscall6" => Function::new_native(ctx, crate::syscalls::___syscall6), + "___syscall9" => Function::new_native(ctx, crate::syscalls::___syscall9), + "___syscall10" => Function::new_native(ctx, crate::syscalls::___syscall10), + "___syscall12" => Function::new_native(ctx, crate::syscalls::___syscall12), + "___syscall14" => Function::new_native(ctx, crate::syscalls::___syscall14), + "___syscall15" => Function::new_native(ctx, crate::syscalls::___syscall15), + "___syscall20" => Function::new_native(ctx, crate::syscalls::___syscall20), + "___syscall21" => Function::new_native(ctx, crate::syscalls::___syscall21), + "___syscall25" => Function::new_native(ctx, crate::syscalls::___syscall25), + "___syscall29" => Function::new_native(ctx, crate::syscalls::___syscall29), + "___syscall32" => Function::new_native(ctx, crate::syscalls::___syscall32), + "___syscall33" => Function::new_native(ctx, crate::syscalls::___syscall33), + "___syscall34" => Function::new_native(ctx, crate::syscalls::___syscall34), + "___syscall36" => Function::new_native(ctx, crate::syscalls::___syscall36), + "___syscall39" => Function::new_native(ctx, crate::syscalls::___syscall39), + "___syscall38" => Function::new_native(ctx, crate::syscalls::___syscall38), + "___syscall40" => Function::new_native(ctx, crate::syscalls::___syscall40), + "___syscall41" => Function::new_native(ctx, crate::syscalls::___syscall41), + "___syscall42" => Function::new_native(ctx, crate::syscalls::___syscall42), + "___syscall51" => Function::new_native(ctx, crate::syscalls::___syscall51), + "___syscall52" => Function::new_native(ctx, crate::syscalls::___syscall52), + "___syscall53" => Function::new_native(ctx, crate::syscalls::___syscall53), + "___syscall54" => Function::new_native(ctx, crate::syscalls::___syscall54), + "___syscall57" => Function::new_native(ctx, crate::syscalls::___syscall57), + "___syscall60" => Function::new_native(ctx, crate::syscalls::___syscall60), + "___syscall63" => Function::new_native(ctx, crate::syscalls::___syscall63), + "___syscall64" => Function::new_native(ctx, crate::syscalls::___syscall64), + "___syscall66" => Function::new_native(ctx, crate::syscalls::___syscall66), + "___syscall75" => Function::new_native(ctx, crate::syscalls::___syscall75), + "___syscall77" => Function::new_native(ctx, crate::syscalls::___syscall77), + "___syscall83" => Function::new_native(ctx, crate::syscalls::___syscall83), + "___syscall85" => Function::new_native(ctx, crate::syscalls::___syscall85), + "___syscall91" => Function::new_native(ctx, crate::syscalls::___syscall91), + "___syscall94" => Function::new_native(ctx, crate::syscalls::___syscall94), + "___syscall96" => Function::new_native(ctx, crate::syscalls::___syscall96), + "___syscall97" => Function::new_native(ctx, crate::syscalls::___syscall97), + "___syscall102" => Function::new_native(ctx, crate::syscalls::___syscall102), + "___syscall110" => Function::new_native(ctx, crate::syscalls::___syscall110), + "___syscall114" => Function::new_native(ctx, crate::syscalls::___syscall114), + "___syscall118" => Function::new_native(ctx, crate::syscalls::___syscall118), + "___syscall121" => Function::new_native(ctx, crate::syscalls::___syscall121), + "___syscall122" => Function::new_native(ctx, crate::syscalls::___syscall122), + "___syscall125" => Function::new_native(ctx, crate::syscalls::___syscall125), + "___syscall132" => Function::new_native(ctx, crate::syscalls::___syscall132), + "___syscall133" => Function::new_native(ctx, crate::syscalls::___syscall133), + "___syscall140" => Function::new_native(ctx, crate::syscalls::___syscall140), + "___syscall142" => Function::new_native(ctx, crate::syscalls::___syscall142), + "___syscall144" => Function::new_native(ctx, crate::syscalls::___syscall144), + "___syscall145" => Function::new_native(ctx, crate::syscalls::___syscall145), + "___syscall146" => Function::new_native(ctx, crate::syscalls::___syscall146), + "___syscall147" => Function::new_native(ctx, crate::syscalls::___syscall147), + "___syscall148" => Function::new_native(ctx, crate::syscalls::___syscall148), + "___syscall150" => Function::new_native(ctx, crate::syscalls::___syscall150), + "___syscall151" => Function::new_native(ctx, crate::syscalls::___syscall151), + "___syscall152" => Function::new_native(ctx, crate::syscalls::___syscall152), + "___syscall153" => Function::new_native(ctx, crate::syscalls::___syscall153), + "___syscall163" => Function::new_native(ctx, crate::syscalls::___syscall163), + "___syscall168" => Function::new_native(ctx, crate::syscalls::___syscall168), + "___syscall180" => Function::new_native(ctx, crate::syscalls::___syscall180), + "___syscall181" => Function::new_native(ctx, crate::syscalls::___syscall181), + "___syscall183" => Function::new_native(ctx, crate::syscalls::___syscall183), + "___syscall191" => Function::new_native(ctx, crate::syscalls::___syscall191), + "___syscall192" => Function::new_native(ctx, crate::syscalls::___syscall192), + "___syscall193" => Function::new_native(ctx, crate::syscalls::___syscall193), + "___syscall194" => Function::new_native(ctx, crate::syscalls::___syscall194), + "___syscall195" => Function::new_native(ctx, crate::syscalls::___syscall195), + "___syscall196" => Function::new_native(ctx, crate::syscalls::___syscall196), + "___syscall197" => Function::new_native(ctx, crate::syscalls::___syscall197), + "___syscall198" => Function::new_native(ctx, crate::syscalls::___syscall198), + "___syscall199" => Function::new_native(ctx, crate::syscalls::___syscall199), + "___syscall200" => Function::new_native(ctx, crate::syscalls::___syscall200), + "___syscall201" => Function::new_native(ctx, crate::syscalls::___syscall201), + "___syscall202" => Function::new_native(ctx, crate::syscalls::___syscall202), + "___syscall205" => Function::new_native(ctx, crate::syscalls::___syscall205), + "___syscall207" => Function::new_native(ctx, crate::syscalls::___syscall207), + "___syscall209" => Function::new_native(ctx, crate::syscalls::___syscall209), + "___syscall211" => Function::new_native(ctx, crate::syscalls::___syscall211), + "___syscall212" => Function::new_native(ctx, crate::syscalls::___syscall212), + "___syscall218" => Function::new_native(ctx, crate::syscalls::___syscall218), + "___syscall219" => Function::new_native(ctx, crate::syscalls::___syscall219), + "___syscall220" => Function::new_native(ctx, crate::syscalls::___syscall220), + "___syscall221" => Function::new_native(ctx, crate::syscalls::___syscall221), + "___syscall268" => Function::new_native(ctx, crate::syscalls::___syscall268), + "___syscall269" => Function::new_native(ctx, crate::syscalls::___syscall269), + "___syscall272" => Function::new_native(ctx, crate::syscalls::___syscall272), + "___syscall295" => Function::new_native(ctx, crate::syscalls::___syscall295), + "___syscall296" => Function::new_native(ctx, crate::syscalls::___syscall296), + "___syscall297" => Function::new_native(ctx, crate::syscalls::___syscall297), + "___syscall298" => Function::new_native(ctx, crate::syscalls::___syscall298), + "___syscall300" => Function::new_native(ctx, crate::syscalls::___syscall300), + "___syscall301" => Function::new_native(ctx, crate::syscalls::___syscall301), + "___syscall302" => Function::new_native(ctx, crate::syscalls::___syscall302), + "___syscall303" => Function::new_native(ctx, crate::syscalls::___syscall303), + "___syscall304" => Function::new_native(ctx, crate::syscalls::___syscall304), + "___syscall305" => Function::new_native(ctx, crate::syscalls::___syscall305), + "___syscall306" => Function::new_native(ctx, crate::syscalls::___syscall306), + "___syscall307" => Function::new_native(ctx, crate::syscalls::___syscall307), + "___syscall308" => Function::new_native(ctx, crate::syscalls::___syscall308), + "___syscall320" => Function::new_native(ctx, crate::syscalls::___syscall320), + "___syscall324" => Function::new_native(ctx, crate::syscalls::___syscall324), + "___syscall330" => Function::new_native(ctx, crate::syscalls::___syscall330), + "___syscall331" => Function::new_native(ctx, crate::syscalls::___syscall331), + "___syscall333" => Function::new_native(ctx, crate::syscalls::___syscall333), + "___syscall334" => Function::new_native(ctx, crate::syscalls::___syscall334), + "___syscall337" => Function::new_native(ctx, crate::syscalls::___syscall337), + "___syscall340" => Function::new_native(ctx, crate::syscalls::___syscall340), + "___syscall345" => Function::new_native(ctx, crate::syscalls::___syscall345), // Process - "abort" => Function::new_native_with_env(store, env.clone(), crate::process::em_abort), - "_abort" => Function::new_native_with_env(store, env.clone(), crate::process::_abort), - "_prctl" => Function::new_native_with_env(store, env.clone(), crate::process::_prctl), - "abortStackOverflow" => Function::new_native_with_env(store, env.clone(), crate::process::abort_stack_overflow), - "_llvm_trap" => Function::new_native_with_env(store, env.clone(), crate::process::_llvm_trap), - "_fork" => Function::new_native_with_env(store, env.clone(), crate::process::_fork), - "_exit" => Function::new_native_with_env(store, env.clone(), crate::process::_exit), - "_system" => Function::new_native_with_env(store, env.clone(), crate::process::_system), - "_popen" => Function::new_native_with_env(store, env.clone(), crate::process::_popen), - "_endgrent" => Function::new_native_with_env(store, env.clone(), crate::process::_endgrent), - "_execve" => Function::new_native_with_env(store, env.clone(), crate::process::_execve), - "_kill" => Function::new_native_with_env(store, env.clone(), crate::process::_kill), - "_llvm_stackrestore" => Function::new_native_with_env(store, env.clone(), crate::process::_llvm_stackrestore), - "_llvm_stacksave" => Function::new_native_with_env(store, env.clone(), crate::process::_llvm_stacksave), - "_llvm_eh_typeid_for" => Function::new_native_with_env(store, env.clone(), crate::process::_llvm_eh_typeid_for), - "_raise" => Function::new_native_with_env(store, env.clone(), crate::process::_raise), - "_sem_init" => Function::new_native_with_env(store, env.clone(), crate::process::_sem_init), - "_sem_destroy" => Function::new_native_with_env(store, env.clone(), crate::process::_sem_destroy), - "_sem_post" => Function::new_native_with_env(store, env.clone(), crate::process::_sem_post), - "_sem_wait" => Function::new_native_with_env(store, env.clone(), crate::process::_sem_wait), - "_getgrent" => Function::new_native_with_env(store, env.clone(), crate::process::_getgrent), - "_sched_yield" => Function::new_native_with_env(store, env.clone(), crate::process::_sched_yield), - "_setgrent" => Function::new_native_with_env(store, env.clone(), crate::process::_setgrent), - "_setgroups" => Function::new_native_with_env(store, env.clone(), crate::process::_setgroups), - "_setitimer" => Function::new_native_with_env(store, env.clone(), crate::process::_setitimer), - "_usleep" => Function::new_native_with_env(store, env.clone(), crate::process::_usleep), - "_nanosleep" => Function::new_native_with_env(store, env.clone(), crate::process::_nanosleep), - "_utime" => Function::new_native_with_env(store, env.clone(), crate::process::_utime), - "_utimes" => Function::new_native_with_env(store, env.clone(), crate::process::_utimes), - "_wait" => Function::new_native_with_env(store, env.clone(), crate::process::_wait), - "_wait3" => Function::new_native_with_env(store, env.clone(), crate::process::_wait3), - "_wait4" => Function::new_native_with_env(store, env.clone(), crate::process::_wait4), - "_waitid" => Function::new_native_with_env(store, env.clone(), crate::process::_waitid), - "_waitpid" => Function::new_native_with_env(store, env.clone(), crate::process::_waitpid), + "abort" => Function::new_native(ctx, crate::process::em_abort), + "_abort" => Function::new_native(ctx, crate::process::_abort), + "_prctl" => Function::new_native(ctx, crate::process::_prctl), + "abortStackOverflow" => Function::new_native(ctx, crate::process::abort_stack_overflow), + "_llvm_trap" => Function::new_native(ctx, crate::process::_llvm_trap), + "_fork" => Function::new_native(ctx, crate::process::_fork), + "_exit" => Function::new_native(ctx, crate::process::_exit), + "_system" => Function::new_native(ctx, crate::process::_system), + "_popen" => Function::new_native(ctx, crate::process::_popen), + "_endgrent" => Function::new_native(ctx, crate::process::_endgrent), + "_execve" => Function::new_native(ctx, crate::process::_execve), + "_kill" => Function::new_native(ctx, crate::process::_kill), + "_llvm_stackrestore" => Function::new_native(ctx, crate::process::_llvm_stackrestore), + "_llvm_stacksave" => Function::new_native(ctx, crate::process::_llvm_stacksave), + "_llvm_eh_typeid_for" => Function::new_native(ctx, crate::process::_llvm_eh_typeid_for), + "_raise" => Function::new_native(ctx, crate::process::_raise), + "_sem_init" => Function::new_native(ctx, crate::process::_sem_init), + "_sem_destroy" => Function::new_native(ctx, crate::process::_sem_destroy), + "_sem_post" => Function::new_native(ctx, crate::process::_sem_post), + "_sem_wait" => Function::new_native(ctx, crate::process::_sem_wait), + "_getgrent" => Function::new_native(ctx, crate::process::_getgrent), + "_sched_yield" => Function::new_native(ctx, crate::process::_sched_yield), + "_setgrent" => Function::new_native(ctx, crate::process::_setgrent), + "_setgroups" => Function::new_native(ctx, crate::process::_setgroups), + "_setitimer" => Function::new_native(ctx, crate::process::_setitimer), + "_usleep" => Function::new_native(ctx, crate::process::_usleep), + "_nanosleep" => Function::new_native(ctx, crate::process::_nanosleep), + "_utime" => Function::new_native(ctx, crate::process::_utime), + "_utimes" => Function::new_native(ctx, crate::process::_utimes), + "_wait" => Function::new_native(ctx, crate::process::_wait), + "_wait3" => Function::new_native(ctx, crate::process::_wait3), + "_wait4" => Function::new_native(ctx, crate::process::_wait4), + "_waitid" => Function::new_native(ctx, crate::process::_waitid), + "_waitpid" => Function::new_native(ctx, crate::process::_waitpid), // Emscripten - "_emscripten_asm_const_i" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::asm_const_i), - "_emscripten_exit_with_live_runtime" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::exit_with_live_runtime), + "_emscripten_asm_const_i" => Function::new_native(ctx, crate::emscripten_target::asm_const_i), + "_emscripten_exit_with_live_runtime" => Function::new_native(ctx, crate::emscripten_target::exit_with_live_runtime), // Signal - "_sigemptyset" => Function::new_native_with_env(store, env.clone(), crate::signal::_sigemptyset), - "_sigaddset" => Function::new_native_with_env(store, env.clone(), crate::signal::_sigaddset), - "_sigprocmask" => Function::new_native_with_env(store, env.clone(), crate::signal::_sigprocmask), - "_sigaction" => Function::new_native_with_env(store, env.clone(), crate::signal::_sigaction), - "_signal" => Function::new_native_with_env(store, env.clone(), crate::signal::_signal), - "_sigsuspend" => Function::new_native_with_env(store, env.clone(), crate::signal::_sigsuspend), + "_sigemptyset" => Function::new_native(ctx, crate::signal::_sigemptyset), + "_sigaddset" => Function::new_native(ctx, crate::signal::_sigaddset), + "_sigprocmask" => Function::new_native(ctx, crate::signal::_sigprocmask), + "_sigaction" => Function::new_native(ctx, crate::signal::_sigaction), + "_signal" => Function::new_native(ctx, crate::signal::_signal), + "_sigsuspend" => Function::new_native(ctx, crate::signal::_sigsuspend), // Memory "abortOnCannotGrowMemory" => abort_on_cannot_grow_memory_export, - "_emscripten_memcpy_big" => Function::new_native_with_env(store, env.clone(), crate::memory::_emscripten_memcpy_big), - "_emscripten_get_heap_size" => Function::new_native_with_env(store, env.clone(), crate::memory::_emscripten_get_heap_size), - "_emscripten_resize_heap" => Function::new_native_with_env(store, env.clone(), crate::memory::_emscripten_resize_heap), - "enlargeMemory" => Function::new_native_with_env(store, env.clone(), crate::memory::enlarge_memory), - "segfault" => Function::new_native_with_env(store, env.clone(), crate::memory::segfault), - "alignfault" => Function::new_native_with_env(store, env.clone(), crate::memory::alignfault), - "ftfault" => Function::new_native_with_env(store, env.clone(), crate::memory::ftfault), - "getTotalMemory" => Function::new_native_with_env(store, env.clone(), crate::memory::get_total_memory), - "_sbrk" => Function::new_native_with_env(store, env.clone(), crate::memory::sbrk), - "___map_file" => Function::new_native_with_env(store, env.clone(), crate::memory::___map_file), + "_emscripten_memcpy_big" => Function::new_native(ctx, crate::memory::_emscripten_memcpy_big), + "_emscripten_get_heap_size" => Function::new_native(ctx, crate::memory::_emscripten_get_heap_size), + "_emscripten_resize_heap" => Function::new_native(ctx, crate::memory::_emscripten_resize_heap), + "enlargeMemory" => Function::new_native(ctx, crate::memory::enlarge_memory), + "segfault" => Function::new_native(ctx, crate::memory::segfault), + "alignfault" => Function::new_native(ctx, crate::memory::alignfault), + "ftfault" => Function::new_native(ctx, crate::memory::ftfault), + "getTotalMemory" => Function::new_native(ctx, crate::memory::get_total_memory), + "_sbrk" => Function::new_native(ctx, crate::memory::sbrk), + "___map_file" => Function::new_native(ctx, crate::memory::___map_file), // Exception - "___cxa_allocate_exception" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_allocate_exception), - "___cxa_current_primary_exception" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_current_primary_exception), - "___cxa_decrement_exception_refcount" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_decrement_exception_refcount), - "___cxa_increment_exception_refcount" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_increment_exception_refcount), - "___cxa_rethrow_primary_exception" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_rethrow_primary_exception), - "___cxa_throw" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_throw), - "___cxa_begin_catch" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_begin_catch), - "___cxa_end_catch" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_end_catch), - "___cxa_uncaught_exception" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_uncaught_exception), - "___cxa_pure_virtual" => Function::new_native_with_env(store, env.clone(), crate::exception::___cxa_pure_virtual), + "___cxa_allocate_exception" => Function::new_native(ctx, crate::exception::___cxa_allocate_exception), + "___cxa_current_primary_exception" => Function::new_native(ctx, crate::exception::___cxa_current_primary_exception), + "___cxa_decrement_exception_refcount" => Function::new_native(ctx, crate::exception::___cxa_decrement_exception_refcount), + "___cxa_increment_exception_refcount" => Function::new_native(ctx, crate::exception::___cxa_increment_exception_refcount), + "___cxa_rethrow_primary_exception" => Function::new_native(ctx, crate::exception::___cxa_rethrow_primary_exception), + "___cxa_throw" => Function::new_native(ctx, crate::exception::___cxa_throw), + "___cxa_begin_catch" => Function::new_native(ctx, crate::exception::___cxa_begin_catch), + "___cxa_end_catch" => Function::new_native(ctx, crate::exception::___cxa_end_catch), + "___cxa_uncaught_exception" => Function::new_native(ctx, crate::exception::___cxa_uncaught_exception), + "___cxa_pure_virtual" => Function::new_native(ctx, crate::exception::___cxa_pure_virtual), // Time - "_gettimeofday" => Function::new_native_with_env(store, env.clone(), crate::time::_gettimeofday), - "_clock_getres" => Function::new_native_with_env(store, env.clone(), crate::time::_clock_getres), - "_clock_gettime" => Function::new_native_with_env(store, env.clone(), crate::time::_clock_gettime), - "_clock_settime" => Function::new_native_with_env(store, env.clone(), crate::time::_clock_settime), - "___clock_gettime" => Function::new_native_with_env(store, env.clone(), crate::time::_clock_gettime), - "_clock" => Function::new_native_with_env(store, env.clone(), crate::time::_clock), - "_difftime" => Function::new_native_with_env(store, env.clone(), crate::time::_difftime), - "_asctime" => Function::new_native_with_env(store, env.clone(), crate::time::_asctime), - "_asctime_r" => Function::new_native_with_env(store, env.clone(), crate::time::_asctime_r), - "_localtime" => Function::new_native_with_env(store, env.clone(), crate::time::_localtime), - "_time" => Function::new_native_with_env(store, env.clone(), crate::time::_time), - "_timegm" => Function::new_native_with_env(store, env.clone(), crate::time::_timegm), - "_strftime" => Function::new_native_with_env(store, env.clone(), crate::time::_strftime), - "_strftime_l" => Function::new_native_with_env(store, env.clone(), crate::time::_strftime_l), - "_localtime_r" => Function::new_native_with_env(store, env.clone(), crate::time::_localtime_r), - "_gmtime_r" => Function::new_native_with_env(store, env.clone(), crate::time::_gmtime_r), - "_ctime" => Function::new_native_with_env(store, env.clone(), crate::time::_ctime), - "_ctime_r" => Function::new_native_with_env(store, env.clone(), crate::time::_ctime_r), - "_mktime" => Function::new_native_with_env(store, env.clone(), crate::time::_mktime), - "_gmtime" => Function::new_native_with_env(store, env.clone(), crate::time::_gmtime), + "_gettimeofday" => Function::new_native(ctx, crate::time::_gettimeofday), + "_clock_getres" => Function::new_native(ctx, crate::time::_clock_getres), + "_clock_gettime" => Function::new_native(ctx, crate::time::_clock_gettime), + "_clock_settime" => Function::new_native(ctx, crate::time::_clock_settime), + "___clock_gettime" => Function::new_native(ctx, crate::time::_clock_gettime), + "_clock" => Function::new_native(ctx, crate::time::_clock), + "_difftime" => Function::new_native(ctx, crate::time::_difftime), + "_asctime" => Function::new_native(ctx, crate::time::_asctime), + "_asctime_r" => Function::new_native(ctx, crate::time::_asctime_r), + "_localtime" => Function::new_native(ctx, crate::time::_localtime), + "_time" => Function::new_native(ctx, crate::time::_time), + "_timegm" => Function::new_native(ctx, crate::time::_timegm), + "_strftime" => Function::new_native(ctx, crate::time::_strftime), + "_strftime_l" => Function::new_native(ctx, crate::time::_strftime_l), + "_localtime_r" => Function::new_native(ctx, crate::time::_localtime_r), + "_gmtime_r" => Function::new_native(ctx, crate::time::_gmtime_r), + "_ctime" => Function::new_native(ctx, crate::time::_ctime), + "_ctime_r" => Function::new_native(ctx, crate::time::_ctime_r), + "_mktime" => Function::new_native(ctx, crate::time::_mktime), + "_gmtime" => Function::new_native(ctx, crate::time::_gmtime), // Math - "sqrt" => Function::new_native(store, crate::math::sqrt), - "floor" => Function::new_native(store, crate::math::floor), - "fabs" => Function::new_native(store, crate::math::fabs), - "f64-rem" => Function::new_native(store, crate::math::f64_rem), - "_llvm_copysign_f32" => Function::new_native(store, crate::math::_llvm_copysign_f32), - "_llvm_copysign_f64" => Function::new_native(store, crate::math::_llvm_copysign_f64), - "_llvm_log10_f64" => Function::new_native(store, crate::math::_llvm_log10_f64), - "_llvm_log2_f64" => Function::new_native(store, crate::math::_llvm_log2_f64), - "_llvm_log10_f32" => Function::new_native(store, crate::math::_llvm_log10_f32), - "_llvm_log2_f32" => Function::new_native(store, crate::math::_llvm_log2_f64), - "_llvm_sin_f64" => Function::new_native(store, crate::math::_llvm_sin_f64), - "_llvm_cos_f64" => Function::new_native(store, crate::math::_llvm_cos_f64), - "_llvm_exp2_f32" => Function::new_native(store, crate::math::_llvm_exp2_f32), - "_llvm_exp2_f64" => Function::new_native(store, crate::math::_llvm_exp2_f64), - "_llvm_trunc_f64" => Function::new_native(store, crate::math::_llvm_trunc_f64), - "_llvm_fma_f64" => Function::new_native(store, crate::math::_llvm_fma_f64), - "_emscripten_random" => Function::new_native_with_env(store, env.clone(), crate::math::_emscripten_random), + "sqrt" => Function::new_native(ctx, crate::math::sqrt), + "floor" => Function::new_native(ctx, crate::math::floor), + "fabs" => Function::new_native(ctx, crate::math::fabs), + "f64-rem" => Function::new_native(ctx, crate::math::f64_rem), + "_llvm_copysign_f32" => Function::new_native(ctx, crate::math::_llvm_copysign_f32), + "_llvm_copysign_f64" => Function::new_native(ctx, crate::math::_llvm_copysign_f64), + "_llvm_log10_f64" => Function::new_native(ctx, crate::math::_llvm_log10_f64), + "_llvm_log2_f64" => Function::new_native(ctx, crate::math::_llvm_log2_f64), + "_llvm_log10_f32" => Function::new_native(ctx, crate::math::_llvm_log10_f32), + "_llvm_log2_f32" => Function::new_native(ctx, crate::math::_llvm_log2_f64), + "_llvm_sin_f64" => Function::new_native(ctx, crate::math::_llvm_sin_f64), + "_llvm_cos_f64" => Function::new_native(ctx, crate::math::_llvm_cos_f64), + "_llvm_exp2_f32" => Function::new_native(ctx, crate::math::_llvm_exp2_f32), + "_llvm_exp2_f64" => Function::new_native(ctx, crate::math::_llvm_exp2_f64), + "_llvm_trunc_f64" => Function::new_native(ctx, crate::math::_llvm_trunc_f64), + "_llvm_fma_f64" => Function::new_native(ctx, crate::math::_llvm_fma_f64), + "_emscripten_random" => Function::new_native(ctx, crate::math::_emscripten_random), // Jump - "__setjmp" => Function::new_native_with_env(store, env.clone(), crate::jmp::__setjmp), - "__longjmp" => Function::new_native_with_env(store, env.clone(), crate::jmp::__longjmp), - "_longjmp" => Function::new_native_with_env(store, env.clone(), crate::jmp::_longjmp), - "_emscripten_longjmp" => Function::new_native_with_env(store, env.clone(), crate::jmp::_longjmp), + "__setjmp" => Function::new_native(ctx, crate::jmp::__setjmp), + "__longjmp" => Function::new_native(ctx, crate::jmp::__longjmp), + "_longjmp" => Function::new_native(ctx, crate::jmp::_longjmp), + "_emscripten_longjmp" => Function::new_native(ctx, crate::jmp::_longjmp), // Bitwise - "_llvm_bswap_i64" => Function::new_native_with_env(store, env.clone(), crate::bitwise::_llvm_bswap_i64), + "_llvm_bswap_i64" => Function::new_native(ctx, crate::bitwise::_llvm_bswap_i64), // libc - "_execv" => Function::new_native(store, crate::libc::execv), - "_endpwent" => Function::new_native(store, crate::libc::endpwent), - "_fexecve" => Function::new_native(store, crate::libc::fexecve), - "_fpathconf" => Function::new_native(store, crate::libc::fpathconf), - "_getitimer" => Function::new_native(store, crate::libc::getitimer), - "_getpwent" => Function::new_native(store, crate::libc::getpwent), - "_killpg" => Function::new_native(store, crate::libc::killpg), - "_pathconf" => Function::new_native_with_env(store, env.clone(), crate::libc::pathconf), - "_siginterrupt" => Function::new_native_with_env(store, env.clone(), crate::signal::_siginterrupt), - "_setpwent" => Function::new_native(store, crate::libc::setpwent), - "_sigismember" => Function::new_native(store, crate::libc::sigismember), - "_sigpending" => Function::new_native(store, crate::libc::sigpending), - "___libc_current_sigrtmax" => Function::new_native(store, crate::libc::current_sigrtmax), - "___libc_current_sigrtmin" => Function::new_native(store, crate::libc::current_sigrtmin), + "_execv" => Function::new_native(ctx, crate::libc::execv), + "_endpwent" => Function::new_native(ctx, crate::libc::endpwent), + "_fexecve" => Function::new_native(ctx, crate::libc::fexecve), + "_fpathconf" => Function::new_native(ctx, crate::libc::fpathconf), + "_getitimer" => Function::new_native(ctx, crate::libc::getitimer), + "_getpwent" => Function::new_native(ctx, crate::libc::getpwent), + "_killpg" => Function::new_native(ctx, crate::libc::killpg), + "_pathconf" => Function::new_native(ctx, crate::libc::pathconf), + "_siginterrupt" => Function::new_native(ctx, crate::signal::_siginterrupt), + "_setpwent" => Function::new_native(ctx, crate::libc::setpwent), + "_sigismember" => Function::new_native(ctx, crate::libc::sigismember), + "_sigpending" => Function::new_native(ctx, crate::libc::sigpending), + "___libc_current_sigrtmax" => Function::new_native(ctx, crate::libc::current_sigrtmax), + "___libc_current_sigrtmin" => Function::new_native(ctx, crate::libc::current_sigrtmin), // Linking - "_dlclose" => Function::new_native_with_env(store, env.clone(), crate::linking::_dlclose), - "_dlerror" => Function::new_native_with_env(store, env.clone(), crate::linking::_dlerror), - "_dlopen" => Function::new_native_with_env(store, env.clone(), crate::linking::_dlopen), - "_dlsym" => Function::new_native_with_env(store, env.clone(), crate::linking::_dlsym), + "_dlclose" => Function::new_native(ctx, crate::linking::_dlclose), + "_dlerror" => Function::new_native(ctx, crate::linking::_dlerror), + "_dlopen" => Function::new_native(ctx, crate::linking::_dlopen), + "_dlsym" => Function::new_native(ctx, crate::linking::_dlsym), // wasm32-unknown-emscripten - "_alarm" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_alarm), - "_atexit" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_atexit), - "setTempRet0" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::setTempRet0), - "getTempRet0" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::getTempRet0), - "invoke_i" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_i), - "invoke_ii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_ii), - "invoke_iii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iii), - "invoke_iiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiii), - "invoke_iifi" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iifi), - "invoke_v" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_v), - "invoke_vi" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vi), - "invoke_vj" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vj), - "invoke_vjji" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vjji), - "invoke_vii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vii), - "invoke_viii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viii), - "invoke_viiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiii), - "__Unwind_Backtrace" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::__Unwind_Backtrace), - "__Unwind_FindEnclosingFunction" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::__Unwind_FindEnclosingFunction), - "__Unwind_GetIPInfo" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::__Unwind_GetIPInfo), - "___cxa_find_matching_catch_2" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::___cxa_find_matching_catch_2), - "___cxa_find_matching_catch_3" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::___cxa_find_matching_catch_3), - "___cxa_free_exception" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::___cxa_free_exception), - "___resumeException" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::___resumeException), - "_dladdr" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_dladdr), - "_pthread_attr_destroy" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_attr_destroy), - "_pthread_attr_getstack" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_attr_getstack), - "_pthread_attr_init" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_attr_init), - "_pthread_attr_setstacksize" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_attr_setstacksize), - "_pthread_cleanup_pop" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_cleanup_pop), - "_pthread_cleanup_push" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_cleanup_push), - "_pthread_cond_destroy" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_cond_destroy), - "_pthread_cond_init" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_cond_init), - "_pthread_cond_signal" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_cond_signal), - "_pthread_cond_timedwait" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_cond_timedwait), - "_pthread_cond_wait" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_cond_wait), - "_pthread_condattr_destroy" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_condattr_destroy), - "_pthread_condattr_init" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_condattr_init), - "_pthread_condattr_setclock" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_condattr_setclock), - "_pthread_create" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_create), - "_pthread_detach" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_detach), - "_pthread_equal" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_equal), - "_pthread_exit" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_exit), - "_pthread_self" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_self), - "_pthread_getattr_np" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_getattr_np), - "_pthread_getspecific" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_getspecific), - "_pthread_join" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_join), - "_pthread_key_create" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_key_create), - "_pthread_mutex_destroy" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_mutex_destroy), - "_pthread_mutex_init" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_mutex_init), - "_pthread_mutexattr_destroy" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_mutexattr_destroy), - "_pthread_mutexattr_init" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_mutexattr_init), - "_pthread_mutexattr_settype" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_mutexattr_settype), - "_pthread_once" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_once), - "_pthread_rwlock_destroy" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_rwlock_destroy), - "_pthread_rwlock_init" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_rwlock_init), - "_pthread_rwlock_rdlock" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_rwlock_rdlock), - "_pthread_rwlock_unlock" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_rwlock_unlock), - "_pthread_rwlock_wrlock" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_rwlock_wrlock), - "_pthread_setcancelstate" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_setcancelstate), - "_pthread_setspecific" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_setspecific), - "_pthread_sigmask" => Function::new_native_with_env(store, env.clone(), crate::pthread::_pthread_sigmask), - "___gxx_personality_v0" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::___gxx_personality_v0), - "_gai_strerror" => Function::new_native_with_env(store, env.clone(), crate::env::_gai_strerror), - "_getdtablesize" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_getdtablesize), - "_gethostbyaddr" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_gethostbyaddr), - "_gethostbyname" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_gethostbyname), - "_gethostbyname_r" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_gethostbyname_r), - "_getloadavg" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_getloadavg), - "_getnameinfo" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::_getnameinfo), - "invoke_dii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_dii), - "invoke_diiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_diiii), - "invoke_iiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiiii), - "invoke_iiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiiiii), - "invoke_iiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiiiiii), - "invoke_iiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiiiiiii), - "invoke_iiiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiiiiiiii), - "invoke_iiiiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiiiiiiiii), - "invoke_iiiiiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiiiiiiiiii), - "invoke_vd" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vd), - "invoke_viiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiiii), - "invoke_viiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiiiii), - "invoke_viiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiiiiii), - "invoke_viiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiiiiiii), - "invoke_viiiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiiiiiiii), - "invoke_viiiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiiiiiiii), - "invoke_viiiiiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiiiiiiiii), - "invoke_iij" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iij), - "invoke_iji" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iji), - "invoke_iiji" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiji), - "invoke_iiijj" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_iiijj), - "invoke_j" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_j), - "invoke_ji" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_ji), - "invoke_jii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_jii), - "invoke_jij" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_jij), - "invoke_jjj" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_jjj), - "invoke_viiij" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiij), - "invoke_viiijiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiijiiii), - "invoke_viiijiiiiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiijiiiiii), - "invoke_viij" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viij), - "invoke_viiji" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viiji), - "invoke_viijiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viijiii), - "invoke_viijj" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viijj), - "invoke_vij" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vij), - "invoke_viji" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viji), - "invoke_vijiii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vijiii), - "invoke_vijj" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vijj), - "invoke_vidd" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_vidd), - "invoke_viid" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viid), - "invoke_viidii" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viidii), - "invoke_viidddddddd" => Function::new_native_with_env(store, env.clone(), crate::emscripten_target::invoke_viidddddddd), + "_alarm" => Function::new_native(ctx, crate::emscripten_target::_alarm), + "_atexit" => Function::new_native(ctx, crate::emscripten_target::_atexit), + "setTempRet0" => Function::new_native(ctx, crate::emscripten_target::setTempRet0), + "getTempRet0" => Function::new_native(ctx, crate::emscripten_target::getTempRet0), + "invoke_i" => Function::new_native(ctx, crate::emscripten_target::invoke_i), + "invoke_ii" => Function::new_native(ctx, crate::emscripten_target::invoke_ii), + "invoke_iii" => Function::new_native(ctx, crate::emscripten_target::invoke_iii), + "invoke_iiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiii), + "invoke_iifi" => Function::new_native(ctx, crate::emscripten_target::invoke_iifi), + "invoke_v" => Function::new_native(ctx, crate::emscripten_target::invoke_v), + "invoke_vi" => Function::new_native(ctx, crate::emscripten_target::invoke_vi), + "invoke_vj" => Function::new_native(ctx, crate::emscripten_target::invoke_vj), + "invoke_vjji" => Function::new_native(ctx, crate::emscripten_target::invoke_vjji), + "invoke_vii" => Function::new_native(ctx, crate::emscripten_target::invoke_vii), + "invoke_viii" => Function::new_native(ctx, crate::emscripten_target::invoke_viii), + "invoke_viiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiii), + "__Unwind_Backtrace" => Function::new_native(ctx, crate::emscripten_target::__Unwind_Backtrace), + "__Unwind_FindEnclosingFunction" => Function::new_native(ctx, crate::emscripten_target::__Unwind_FindEnclosingFunction), + "__Unwind_GetIPInfo" => Function::new_native(ctx, crate::emscripten_target::__Unwind_GetIPInfo), + "___cxa_find_matching_catch_2" => Function::new_native(ctx, crate::emscripten_target::___cxa_find_matching_catch_2), + "___cxa_find_matching_catch_3" => Function::new_native(ctx, crate::emscripten_target::___cxa_find_matching_catch_3), + "___cxa_free_exception" => Function::new_native(ctx, crate::emscripten_target::___cxa_free_exception), + "___resumeException" => Function::new_native(ctx, crate::emscripten_target::___resumeException), + "_dladdr" => Function::new_native(ctx, crate::emscripten_target::_dladdr), + "_pthread_attr_destroy" => Function::new_native(ctx, crate::pthread::_pthread_attr_destroy), + "_pthread_attr_getstack" => Function::new_native(ctx, crate::pthread::_pthread_attr_getstack), + "_pthread_attr_init" => Function::new_native(ctx, crate::pthread::_pthread_attr_init), + "_pthread_attr_setstacksize" => Function::new_native(ctx, crate::pthread::_pthread_attr_setstacksize), + "_pthread_cleanup_pop" => Function::new_native(ctx, crate::pthread::_pthread_cleanup_pop), + "_pthread_cleanup_push" => Function::new_native(ctx, crate::pthread::_pthread_cleanup_push), + "_pthread_cond_destroy" => Function::new_native(ctx, crate::pthread::_pthread_cond_destroy), + "_pthread_cond_init" => Function::new_native(ctx, crate::pthread::_pthread_cond_init), + "_pthread_cond_signal" => Function::new_native(ctx, crate::pthread::_pthread_cond_signal), + "_pthread_cond_timedwait" => Function::new_native(ctx, crate::pthread::_pthread_cond_timedwait), + "_pthread_cond_wait" => Function::new_native(ctx, crate::pthread::_pthread_cond_wait), + "_pthread_condattr_destroy" => Function::new_native(ctx, crate::pthread::_pthread_condattr_destroy), + "_pthread_condattr_init" => Function::new_native(ctx, crate::pthread::_pthread_condattr_init), + "_pthread_condattr_setclock" => Function::new_native(ctx, crate::pthread::_pthread_condattr_setclock), + "_pthread_create" => Function::new_native(ctx, crate::pthread::_pthread_create), + "_pthread_detach" => Function::new_native(ctx, crate::pthread::_pthread_detach), + "_pthread_equal" => Function::new_native(ctx, crate::pthread::_pthread_equal), + "_pthread_exit" => Function::new_native(ctx, crate::pthread::_pthread_exit), + "_pthread_self" => Function::new_native(ctx, crate::pthread::_pthread_self), + "_pthread_getattr_np" => Function::new_native(ctx, crate::pthread::_pthread_getattr_np), + "_pthread_getspecific" => Function::new_native(ctx, crate::pthread::_pthread_getspecific), + "_pthread_join" => Function::new_native(ctx, crate::pthread::_pthread_join), + "_pthread_key_create" => Function::new_native(ctx, crate::pthread::_pthread_key_create), + "_pthread_mutex_destroy" => Function::new_native(ctx, crate::pthread::_pthread_mutex_destroy), + "_pthread_mutex_init" => Function::new_native(ctx, crate::pthread::_pthread_mutex_init), + "_pthread_mutexattr_destroy" => Function::new_native(ctx, crate::pthread::_pthread_mutexattr_destroy), + "_pthread_mutexattr_init" => Function::new_native(ctx, crate::pthread::_pthread_mutexattr_init), + "_pthread_mutexattr_settype" => Function::new_native(ctx, crate::pthread::_pthread_mutexattr_settype), + "_pthread_once" => Function::new_native(ctx, crate::pthread::_pthread_once), + "_pthread_rwlock_destroy" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_destroy), + "_pthread_rwlock_init" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_init), + "_pthread_rwlock_rdlock" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_rdlock), + "_pthread_rwlock_unlock" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_unlock), + "_pthread_rwlock_wrlock" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_wrlock), + "_pthread_setcancelstate" => Function::new_native(ctx, crate::pthread::_pthread_setcancelstate), + "_pthread_setspecific" => Function::new_native(ctx, crate::pthread::_pthread_setspecific), + "_pthread_sigmask" => Function::new_native(ctx, crate::pthread::_pthread_sigmask), + "___gxx_personality_v0" => Function::new_native(ctx, crate::emscripten_target::___gxx_personality_v0), + "_gai_strerror" => Function::new_native(ctx, crate::env::_gai_strerror), + "_getdtablesize" => Function::new_native(ctx, crate::emscripten_target::_getdtablesize), + "_gethostbyaddr" => Function::new_native(ctx, crate::emscripten_target::_gethostbyaddr), + "_gethostbyname" => Function::new_native(ctx, crate::emscripten_target::_gethostbyname), + "_gethostbyname_r" => Function::new_native(ctx, crate::emscripten_target::_gethostbyname_r), + "_getloadavg" => Function::new_native(ctx, crate::emscripten_target::_getloadavg), + "_getnameinfo" => Function::new_native(ctx, crate::emscripten_target::_getnameinfo), + "invoke_dii" => Function::new_native(ctx, crate::emscripten_target::invoke_dii), + "invoke_diiii" => Function::new_native(ctx, crate::emscripten_target::invoke_diiii), + "invoke_iiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiii), + "invoke_iiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiii), + "invoke_iiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiii), + "invoke_iiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiii), + "invoke_iiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiiii), + "invoke_iiiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiiiii), + "invoke_iiiiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiiiiii), + "invoke_vd" => Function::new_native(ctx, crate::emscripten_target::invoke_vd), + "invoke_viiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiii), + "invoke_viiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiii), + "invoke_viiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiii), + "invoke_viiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiii), + "invoke_viiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiiii), + "invoke_viiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiiii), + "invoke_viiiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiiiii), + "invoke_iij" => Function::new_native(ctx, crate::emscripten_target::invoke_iij), + "invoke_iji" => Function::new_native(ctx, crate::emscripten_target::invoke_iji), + "invoke_iiji" => Function::new_native(ctx, crate::emscripten_target::invoke_iiji), + "invoke_iiijj" => Function::new_native(ctx, crate::emscripten_target::invoke_iiijj), + "invoke_j" => Function::new_native(ctx, crate::emscripten_target::invoke_j), + "invoke_ji" => Function::new_native(ctx, crate::emscripten_target::invoke_ji), + "invoke_jii" => Function::new_native(ctx, crate::emscripten_target::invoke_jii), + "invoke_jij" => Function::new_native(ctx, crate::emscripten_target::invoke_jij), + "invoke_jjj" => Function::new_native(ctx, crate::emscripten_target::invoke_jjj), + "invoke_viiij" => Function::new_native(ctx, crate::emscripten_target::invoke_viiij), + "invoke_viiijiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiijiiii), + "invoke_viiijiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiijiiiiii), + "invoke_viij" => Function::new_native(ctx, crate::emscripten_target::invoke_viij), + "invoke_viiji" => Function::new_native(ctx, crate::emscripten_target::invoke_viiji), + "invoke_viijiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viijiii), + "invoke_viijj" => Function::new_native(ctx, crate::emscripten_target::invoke_viijj), + "invoke_vij" => Function::new_native(ctx, crate::emscripten_target::invoke_vij), + "invoke_viji" => Function::new_native(ctx, crate::emscripten_target::invoke_viji), + "invoke_vijiii" => Function::new_native(ctx, crate::emscripten_target::invoke_vijiii), + "invoke_vijj" => Function::new_native(ctx, crate::emscripten_target::invoke_vijj), + "invoke_vidd" => Function::new_native(ctx, crate::emscripten_target::invoke_vidd), + "invoke_viid" => Function::new_native(ctx, crate::emscripten_target::invoke_viid), + "invoke_viidii" => Function::new_native(ctx, crate::emscripten_target::invoke_viidii), + "invoke_viidddddddd" => Function::new_native(ctx, crate::emscripten_target::invoke_viidddddddd), // ucontext - "_getcontext" => Function::new_native_with_env(store, env.clone(), crate::ucontext::_getcontext), - "_makecontext" => Function::new_native_with_env(store, env.clone(), crate::ucontext::_makecontext), - "_setcontext" => Function::new_native_with_env(store, env.clone(), crate::ucontext::_setcontext), - "_swapcontext" => Function::new_native_with_env(store, env.clone(), crate::ucontext::_swapcontext), + "_getcontext" => Function::new_native(ctx, crate::ucontext::_getcontext), + "_makecontext" => Function::new_native(ctx, crate::ucontext::_makecontext), + "_setcontext" => Function::new_native(ctx, crate::ucontext::_setcontext), + "_swapcontext" => Function::new_native(ctx, crate::ucontext::_swapcontext), // unistd - "_confstr" => Function::new_native_with_env(store, env.clone(), crate::unistd::confstr), + "_confstr" => Function::new_native(ctx, crate::unistd::confstr), }; // Compatibility with newer versions of Emscripten @@ -1040,31 +1459,31 @@ pub fn generate_emscripten_env( for null_function_name in globals.null_function_names.iter() { env_ns.insert( null_function_name.as_str(), - Function::new_native_with_env(store, env.clone(), nullfunc), + Function::new_native(ctx, nullfunc), ); } let import_object: Imports = imports! { "env" => env_ns, "global" => { - "NaN" => Global::new(store, Val::F64(f64::NAN)), - "Infinity" => Global::new(store, Val::F64(f64::INFINITY)), + "NaN" => Global::new(ctx, Value::F64(f64::NAN)), + "Infinity" => Global::new(ctx, Value::F64(f64::INFINITY)), }, "global.Math" => { - "pow" => Function::new_native(store, crate::math::pow), - "exp" => Function::new_native(store, crate::math::exp), - "log" => Function::new_native(store, crate::math::log), + "pow" => Function::new_native(ctx, crate::math::pow), + "exp" => Function::new_native(ctx, crate::math::exp), + "log" => Function::new_native(ctx, crate::math::log), }, "asm2wasm" => { - "f64-rem" => Function::new_native(store, crate::math::f64_rem), - "f64-to-int" => Function::new_native(store, crate::math::f64_to_int), + "f64-rem" => Function::new_native(ctx, crate::math::f64_rem), + "f64-to-int" => Function::new_native(ctx, crate::math::f64_to_int), }, }; import_object } -pub fn nullfunc(ctx: &EmEnv, _x: u32) { +pub fn nullfunc(ctx: ContextMut<'_, EmEnv>, _x: u32) { use crate::process::abort_with_message; debug!("emscripten::nullfunc_i {}", _x); abort_with_message( diff --git a/lib/emscripten/src/libc.rs b/lib/emscripten/src/libc.rs index 81d67971da2..3916a553b48 100644 --- a/lib/emscripten/src/libc.rs +++ b/lib/emscripten/src/libc.rs @@ -1,76 +1,77 @@ extern crate libc; use crate::EmEnv; +use wasmer::ContextMut; #[cfg(unix)] use std::convert::TryInto; -pub fn current_sigrtmax() -> i32 { +pub fn current_sigrtmax(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::current_sigrtmax"); 0 } -pub fn current_sigrtmin() -> i32 { +pub fn current_sigrtmin(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::current_sigrtmin"); 0 } -pub fn endpwent() { +pub fn endpwent(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::endpwent"); } -pub fn execv(_a: i32, _b: i32) -> i32 { +pub fn execv(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::execv"); 0 } -pub fn fexecve(_a: i32, _b: i32, _c: i32) -> i32 { +pub fn fexecve(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32) -> i32 { debug!("emscripten::fexecve"); 0 } -pub fn fpathconf(_a: i32, _b: i32) -> i32 { +pub fn fpathconf(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::fpathconf"); 0 } -pub fn getitimer(_a: i32, _b: i32) -> i32 { +pub fn getitimer(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::getitimer"); 0 } -pub fn getpwent() -> i32 { +pub fn getpwent(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::getpwent"); 0 } -pub fn killpg(_a: i32, _b: i32) -> i32 { +pub fn killpg(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::killpg"); 0 } #[cfg(unix)] -pub fn pathconf(ctx: &EmEnv, path_ptr: i32, name: i32) -> i32 { +pub fn pathconf(ctx: ContextMut<'_, EmEnv>, path_ptr: i32, name: i32) -> i32 { debug!("emscripten::pathconf"); - let path = emscripten_memory_pointer!(ctx.memory(0), path_ptr) as *const i8; + let path = emscripten_memory_pointer!(ctx, ctx.data().memory(0), path_ptr) as *const i8; unsafe { libc::pathconf(path as *const _, name).try_into().unwrap() } } #[cfg(not(unix))] -pub fn pathconf(_ctx: &EmEnv, _path_ptr: i32, _name: i32) -> i32 { +pub fn pathconf(_ctx: ContextMut<'_, EmEnv>, _path_ptr: i32, _name: i32) -> i32 { debug!("emscripten::pathconf"); 0 } -pub fn setpwent() { +pub fn setpwent(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::setpwent"); } -pub fn sigismember(_a: i32, _b: i32) -> i32 { +pub fn sigismember(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::sigismember"); 0 } -pub fn sigpending(_a: i32) -> i32 { +pub fn sigpending(_ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { debug!("emscripten::sigpending"); 0 } diff --git a/lib/emscripten/src/linking.rs b/lib/emscripten/src/linking.rs index 5ca49e85e13..585c2e46c8a 100644 --- a/lib/emscripten/src/linking.rs +++ b/lib/emscripten/src/linking.rs @@ -1,27 +1,28 @@ use crate::EmEnv; +use wasmer::ContextMut; // TODO: Need to implement. /// emscripten: dlopen(filename: *const c_char, flag: c_int) -> *mut c_void -pub fn _dlopen(_ctx: &EmEnv, _filename: u32, _flag: u32) -> i32 { +pub fn _dlopen(mut _ctx: ContextMut<'_, EmEnv>, _filename: u32, _flag: u32) -> i32 { debug!("emscripten::_dlopen"); -1 } /// emscripten: dlclose(handle: *mut c_void) -> c_int -pub fn _dlclose(_ctx: &EmEnv, _filename: u32) -> i32 { +pub fn _dlclose(mut _ctx: ContextMut<'_, EmEnv>, _filename: u32) -> i32 { debug!("emscripten::_dlclose"); -1 } /// emscripten: dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void -pub fn _dlsym(_ctx: &EmEnv, _filepath: u32, _symbol: u32) -> i32 { +pub fn _dlsym(mut _ctx: ContextMut<'_, EmEnv>, _filepath: u32, _symbol: u32) -> i32 { debug!("emscripten::_dlsym"); -1 } /// emscripten: dlerror() -> *mut c_char -pub fn _dlerror(_ctx: &EmEnv) -> i32 { +pub fn _dlerror(mut _ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::_dlerror"); -1 } diff --git a/lib/emscripten/src/lock.rs b/lib/emscripten/src/lock.rs index f83b12e38bd..118ff9d5a28 100644 --- a/lib/emscripten/src/lock.rs +++ b/lib/emscripten/src/lock.rs @@ -1,22 +1,29 @@ use crate::EmEnv; use libc::c_int; +use wasmer::ContextMut; // NOTE: Not implemented by Emscripten -pub fn ___lock(_ctx: &EmEnv, _what: c_int) { +pub fn ___lock(mut _ctx: ContextMut<'_, EmEnv>, _what: c_int) { debug!("emscripten::___lock {}", _what); } // NOTE: Not implemented by Emscripten -pub fn ___unlock(_ctx: &EmEnv, _what: c_int) { +pub fn ___unlock(mut _ctx: ContextMut<'_, EmEnv>, _what: c_int) { debug!("emscripten::___unlock {}", _what); } // NOTE: Not implemented by Emscripten -pub fn ___wait(_ctx: &EmEnv, _which: u32, _varargs: u32, _three: u32, _four: u32) { +pub fn ___wait( + mut _ctx: ContextMut<'_, EmEnv>, + _which: u32, + _varargs: u32, + _three: u32, + _four: u32, +) { debug!("emscripten::___wait"); } -pub fn _flock(_ctx: &EmEnv, _fd: u32, _op: u32) -> u32 { +pub fn _flock(mut _ctx: ContextMut<'_, EmEnv>, _fd: u32, _op: u32) -> u32 { debug!("emscripten::_flock"); 0 } diff --git a/lib/emscripten/src/macros.rs b/lib/emscripten/src/macros.rs index 4cd2550b17b..904721fbb19 100644 --- a/lib/emscripten/src/macros.rs +++ b/lib/emscripten/src/macros.rs @@ -1,5 +1,5 @@ macro_rules! emscripten_memory_pointer { - ($memory:expr, $pointer:expr) => { - $memory.data_ptr().wrapping_add($pointer as usize) + ($ctx:expr, $memory:expr, $pointer:expr) => { + $memory.data_ptr(&$ctx).wrapping_add($pointer as usize) }; } diff --git a/lib/emscripten/src/math.rs b/lib/emscripten/src/math.rs index 6328e1853be..896bc3d38f0 100644 --- a/lib/emscripten/src/math.rs +++ b/lib/emscripten/src/math.rs @@ -1,110 +1,111 @@ use crate::EmEnv; +use wasmer::ContextMut; -pub fn _llvm_copysign_f32(x: f64, y: f64) -> f64 { +pub fn _llvm_copysign_f32(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { x.copysign(y) } -pub fn _llvm_copysign_f64(x: f64, y: f64) -> f64 { +pub fn _llvm_copysign_f64(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { x.copysign(y) } /// emscripten: _llvm_log10_f64 -pub fn _llvm_log10_f64(value: f64) -> f64 { +pub fn _llvm_log10_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { debug!("emscripten::_llvm_log10_f64"); value.log10() } /// emscripten: _llvm_log2_f64 -pub fn _llvm_log2_f64(value: f64) -> f64 { +pub fn _llvm_log2_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { debug!("emscripten::_llvm_log2_f64"); value.log2() } /// emscripten: _llvm_sin_f64 -pub fn _llvm_sin_f64(value: f64) -> f64 { +pub fn _llvm_sin_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { debug!("emscripten::_llvm_sin_f64"); value.sin() } /// emscripten: _llvm_cos_f64 -pub fn _llvm_cos_f64(value: f64) -> f64 { +pub fn _llvm_cos_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { debug!("emscripten::_llvm_cos_f64"); value.cos() } -pub fn _llvm_log10_f32(_value: f64) -> f64 { +pub fn _llvm_log10_f32(mut _ctx: ContextMut<'_, EmEnv>, _value: f64) -> f64 { debug!("emscripten::_llvm_log10_f32"); -1.0 } -pub fn _llvm_log2_f32(_value: f64) -> f64 { +pub fn _llvm_log2_f32(mut _ctx: ContextMut<'_, EmEnv>, _value: f64) -> f64 { debug!("emscripten::_llvm_log10_f32"); -1.0 } -pub fn _llvm_exp2_f32(value: f32) -> f32 { +pub fn _llvm_exp2_f32(mut _ctx: ContextMut<'_, EmEnv>, value: f32) -> f32 { debug!("emscripten::_llvm_exp2_f32"); 2f32.powf(value) } -pub fn _llvm_exp2_f64(value: f64) -> f64 { +pub fn _llvm_exp2_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { debug!("emscripten::_llvm_exp2_f64"); 2f64.powf(value) } -pub fn _llvm_trunc_f64(value: f64) -> f64 { +pub fn _llvm_trunc_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { debug!("emscripten::_llvm_trunc_f64"); value.trunc() } -pub fn _llvm_fma_f64(value: f64, a: f64, b: f64) -> f64 { +pub fn _llvm_fma_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64, a: f64, b: f64) -> f64 { debug!("emscripten::_llvm_fma_f64"); value.mul_add(a, b) } -pub fn _emscripten_random(_ctx: &EmEnv) -> f64 { +pub fn _emscripten_random(mut _ctx: ContextMut<'_, EmEnv>) -> f64 { debug!("emscripten::_emscripten_random"); -1.0 } // emscripten: asm2wasm.f64-rem -pub fn f64_rem(x: f64, y: f64) -> f64 { +pub fn f64_rem(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { debug!("emscripten::f64-rem"); x % y } // emscripten: global.Math pow -pub fn pow(x: f64, y: f64) -> f64 { +pub fn pow(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { x.powf(y) } // emscripten: global.Math exp -pub fn exp(value: f64) -> f64 { +pub fn exp(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { value.exp() } // emscripten: global.Math log -pub fn log(value: f64) -> f64 { +pub fn log(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { value.ln() } // emscripten: global.Math sqrt -pub fn sqrt(value: f64) -> f64 { +pub fn sqrt(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { value.sqrt() } // emscripten: global.Math floor -pub fn floor(value: f64) -> f64 { +pub fn floor(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { value.floor() } // emscripten: global.Math fabs -pub fn fabs(value: f64) -> f64 { +pub fn fabs(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { value.abs() } // emscripten: asm2wasm.f64-to-int -pub fn f64_to_int(value: f64) -> i32 { +pub fn f64_to_int(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> i32 { debug!("emscripten::f64_to_int {}", value); value as i32 } diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index aec81dd1511..eccf2d8b5c7 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -3,26 +3,32 @@ use super::process::abort_with_message; use crate::EmEnv; use libc::{c_int, c_void, memcpy, size_t}; // TODO: investigate max pages etc. probably in Wasm Common, maybe reexport -use wasmer::{Pages, WasmPtr, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE}; +use wasmer::{ + AsContextMut, ContextMut, Pages, WasmPtr, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE, +}; /// emscripten: _emscripten_memcpy_big -pub fn _emscripten_memcpy_big(ctx: &EmEnv, dest: u32, src: u32, len: u32) -> u32 { +pub fn _emscripten_memcpy_big(ctx: ContextMut<'_, EmEnv>, dest: u32, src: u32, len: u32) -> u32 { debug!( "emscripten::_emscripten_memcpy_big {}, {}, {}", dest, src, len ); - let dest_addr = emscripten_memory_pointer!(ctx.memory(0), dest) as *mut c_void; - let src_addr = emscripten_memory_pointer!(ctx.memory(0), src) as *mut c_void; + let dest_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), dest) as *mut c_void; + let src_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), src) as *mut c_void; unsafe { memcpy(dest_addr, src_addr, len as size_t); } dest } +fn get_heap_size(ctx: &ContextMut<'_, EmEnv>) -> u32 { + ctx.data().memory(0).size(&ctx).bytes().0 as u32 +} + /// emscripten: _emscripten_get_heap_size -pub fn _emscripten_get_heap_size(ctx: &EmEnv) -> u32 { +pub fn _emscripten_get_heap_size(ctx: ContextMut<'_, EmEnv>) -> u32 { trace!("emscripten::_emscripten_get_heap_size"); - let result = ctx.memory(0).size().bytes().0 as u32; + let result = get_heap_size(&ctx); trace!("=> {}", result); result @@ -36,11 +42,9 @@ fn align_up(mut val: usize, multiple: usize) -> usize { val } -/// emscripten: _emscripten_resize_heap -/// Note: this function only allows growing the size of heap -pub fn _emscripten_resize_heap(ctx: &EmEnv, requested_size: u32) -> u32 { +fn resize_heap(ctx: &mut ContextMut<'_, EmEnv>, requested_size: u32) -> u32 { debug!("emscripten::_emscripten_resize_heap {}", requested_size); - let current_memory_pages = ctx.memory(0).size(); + let current_memory_pages = ctx.data().memory(0).size(&ctx); let current_memory = current_memory_pages.bytes().0 as u32; // implementation from emscripten @@ -60,7 +64,11 @@ pub fn _emscripten_resize_heap(ctx: &EmEnv, requested_size: u32) -> u32 { } let amount_to_grow = (new_size - current_memory as usize) / WASM_PAGE_SIZE; - if let Ok(_pages_allocated) = ctx.memory(0).grow(Pages(amount_to_grow as u32)) { + if let Ok(_pages_allocated) = ctx + .data() + .memory(0) + .grow(&mut ctx.as_context_mut(), Pages(amount_to_grow as u32)) + { debug!("{} pages allocated", _pages_allocated.0); 1 } else { @@ -68,19 +76,23 @@ pub fn _emscripten_resize_heap(ctx: &EmEnv, requested_size: u32) -> u32 { } } +/// emscripten: _emscripten_resize_heap +/// Note: this function only allows growing the size of heap +pub fn _emscripten_resize_heap(mut ctx: ContextMut<'_, EmEnv>, requested_size: u32) -> u32 { + resize_heap(&mut ctx, requested_size) +} + /// emscripten: sbrk -pub fn sbrk(ctx: &EmEnv, increment: i32) -> i32 { +pub fn sbrk(mut ctx: ContextMut<'_, EmEnv>, increment: i32) -> i32 { debug!("emscripten::sbrk"); // let old_dynamic_top = 0; // let new_dynamic_top = 0; - let memory = ctx.memory(0); - let dynamictop_ptr = { - let globals = &get_emscripten_data(ctx).globals; - WasmPtr::::new(globals.dynamictop_ptr).deref(&memory) - }; + let memory = ctx.data().memory(0); + let top_ptr = get_emscripten_data(&ctx).globals.dynamictop_ptr; + let dynamictop_ptr = WasmPtr::::new(top_ptr).deref(&ctx, &memory); let old_dynamic_top = dynamictop_ptr.read().unwrap(); let new_dynamic_top: i32 = old_dynamic_top + increment; - let total_memory = _emscripten_get_heap_size(ctx) as i32; + let total_memory = get_heap_size(&ctx) as i32; debug!( " => PTR {}, old: {}, new: {}, increment: {}, total: {}", dynamictop_ptr.offset(), @@ -94,25 +106,27 @@ pub fn sbrk(ctx: &EmEnv, increment: i32) -> i32 { return -1; } if new_dynamic_top > total_memory { - let resized = _emscripten_resize_heap(ctx, new_dynamic_top as u32); + let resized = resize_heap(&mut ctx, new_dynamic_top as u32); if resized == 0 { return -1; } } + // re-borrow the top ptr + let dynamictop_ptr = WasmPtr::::new(top_ptr).deref(&ctx, &memory); dynamictop_ptr.write(new_dynamic_top).unwrap(); old_dynamic_top as _ } /// emscripten: getTotalMemory -pub fn get_total_memory(_ctx: &EmEnv) -> u32 { +pub fn get_total_memory(ctx: ContextMut<'_, EmEnv>) -> u32 { debug!("emscripten::get_total_memory"); // instance.memories[0].current_pages() // TODO: Fix implementation - _ctx.memory(0).size().bytes().0 as u32 + ctx.data().memory(0).size(&ctx).bytes().0 as u32 } /// emscripten: enlargeMemory -pub fn enlarge_memory(_ctx: &EmEnv) -> u32 { +pub fn enlarge_memory(_ctx: ContextMut<'_, EmEnv>) -> u32 { debug!("emscripten::enlarge_memory"); // instance.memories[0].grow(100); // TODO: Fix implementation @@ -120,7 +134,7 @@ pub fn enlarge_memory(_ctx: &EmEnv) -> u32 { } /// emscripten: abortOnCannotGrowMemory -pub fn abort_on_cannot_grow_memory(ctx: &EmEnv, _requested_size: u32) -> u32 { +pub fn abort_on_cannot_grow_memory(ctx: ContextMut<'_, EmEnv>, _requested_size: u32) -> u32 { debug!( "emscripten::abort_on_cannot_grow_memory {}", _requested_size @@ -130,32 +144,32 @@ pub fn abort_on_cannot_grow_memory(ctx: &EmEnv, _requested_size: u32) -> u32 { } /// emscripten: abortOnCannotGrowMemory -pub fn abort_on_cannot_grow_memory_old(ctx: &EmEnv) -> u32 { +pub fn abort_on_cannot_grow_memory_old(ctx: ContextMut<'_, EmEnv>) -> u32 { debug!("emscripten::abort_on_cannot_grow_memory"); abort_with_message(ctx, "Cannot enlarge memory arrays!"); 0 } /// emscripten: segfault -pub fn segfault(ctx: &EmEnv) { +pub fn segfault(ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::segfault"); abort_with_message(ctx, "segmentation fault"); } /// emscripten: alignfault -pub fn alignfault(ctx: &EmEnv) { +pub fn alignfault(ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::alignfault"); abort_with_message(ctx, "alignment fault"); } /// emscripten: ftfault -pub fn ftfault(ctx: &EmEnv) { +pub fn ftfault(ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::ftfault"); abort_with_message(ctx, "Function table mask error"); } /// emscripten: ___map_file -pub fn ___map_file(_ctx: &EmEnv, _one: u32, _two: u32) -> c_int { +pub fn ___map_file(_ctx: ContextMut<'_, EmEnv>, _one: u32, _two: u32) -> c_int { debug!("emscripten::___map_file"); // NOTE: TODO: Em returns -1 here as well. May need to implement properly -1 diff --git a/lib/emscripten/src/process.rs b/lib/emscripten/src/process.rs index f5fe4eb07d9..665a5fb9b10 100644 --- a/lib/emscripten/src/process.rs +++ b/lib/emscripten/src/process.rs @@ -6,34 +6,35 @@ type PidT = libc::pid_t; type PidT = c_int; use crate::EmEnv; +use wasmer::ContextMut; -pub fn abort_with_message(ctx: &EmEnv, message: &str) { +pub fn abort_with_message(ctx: ContextMut<'_, EmEnv>, message: &str) { debug!("emscripten::abort_with_message"); println!("{}", message); _abort(ctx); } /// The name of this call is `abort` but we want to avoid conflicts with libc::abort -pub fn em_abort(ctx: &EmEnv, arg: u32) { +pub fn em_abort(ctx: ContextMut<'_, EmEnv>, arg: u32) { debug!("emscripten::abort"); eprintln!("Program aborted with value {}", arg); _abort(ctx); } -pub fn _abort(_ctx: &EmEnv) { +pub fn _abort(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::_abort"); unsafe { abort(); } } -pub fn _prctl(ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _prctl(ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { debug!("emscripten::_prctl"); abort_with_message(ctx, "missing function: prctl"); -1 } -pub fn _fork(_ctx: &EmEnv) -> PidT { +pub fn _fork(_ctx: ContextMut<'_, EmEnv>) -> PidT { debug!("emscripten::_fork"); // unsafe { // fork() @@ -41,132 +42,132 @@ pub fn _fork(_ctx: &EmEnv) -> PidT { -1 } -pub fn _endgrent(_ctx: &EmEnv) { +pub fn _endgrent(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::_endgrent"); } -pub fn _execve(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _execve(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_execve"); -1 } #[allow(unreachable_code)] -pub fn _exit(_ctx: &EmEnv, status: c_int) { +pub fn _exit(_ctx: ContextMut<'_, EmEnv>, status: c_int) { // -> ! debug!("emscripten::_exit {}", status); unsafe { exit(status) } } -pub fn _kill(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn _kill(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::_kill"); -1 } -pub fn _sched_yield(_ctx: &EmEnv) -> i32 { +pub fn _sched_yield(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::_sched_yield"); -1 } -pub fn _llvm_stacksave(_ctx: &EmEnv) -> i32 { +pub fn _llvm_stacksave(_ctx: ContextMut<'_, EmEnv>) -> i32 { debug!("emscripten::_llvm_stacksave"); -1 } -pub fn _llvm_stackrestore(_ctx: &EmEnv, _one: i32) { +pub fn _llvm_stackrestore(_ctx: ContextMut<'_, EmEnv>, _one: i32) { debug!("emscripten::_llvm_stackrestore"); } -pub fn _raise(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _raise(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_raise"); -1 } -pub fn _sem_init(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _sem_init(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_sem_init: {}, {}, {}", _one, _two, _three); 0 } -pub fn _sem_destroy(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _sem_destroy(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_sem_destroy"); 0 } -pub fn _sem_post(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _sem_post(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_sem_post"); -1 } -pub fn _sem_wait(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _sem_wait(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_sem_post"); -1 } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrent(_ctx: &EmEnv) -> c_int { +pub fn _getgrent(_ctx: ContextMut<'_, EmEnv>) -> c_int { debug!("emscripten::_getgrent"); -1 } -pub fn _setgrent(_ctx: &EmEnv) { +pub fn _setgrent(_ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::_setgrent"); } -pub fn _setgroups(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn _setgroups(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::_setgroups"); -1 } -pub fn _setitimer(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _setitimer(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_setitimer"); -1 } -pub fn _usleep(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _usleep(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_usleep"); -1 } -pub fn _nanosleep(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn _nanosleep(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::_nanosleep"); -1 } -pub fn _utime(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn _utime(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::_utime"); -1 } -pub fn _utimes(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn _utimes(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::_utimes"); -1 } -pub fn _wait(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _wait(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_wait"); -1 } -pub fn _wait3(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _wait3(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_wait3"); -1 } -pub fn _wait4(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { +pub fn _wait4(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { debug!("emscripten::_wait4"); -1 } -pub fn _waitid(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { +pub fn _waitid(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { debug!("emscripten::_waitid"); -1 } -pub fn _waitpid(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _waitpid(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_waitpid"); -1 } -pub fn abort_stack_overflow(ctx: &EmEnv, _what: c_int) { +pub fn abort_stack_overflow(ctx: ContextMut<'_, EmEnv>, _what: c_int) { debug!("emscripten::abort_stack_overflow"); // TODO: Message incomplete. Need to finish em runtime data first abort_with_message( @@ -175,24 +176,24 @@ pub fn abort_stack_overflow(ctx: &EmEnv, _what: c_int) { ); } -pub fn _llvm_trap(ctx: &EmEnv) { +pub fn _llvm_trap(ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::_llvm_trap"); abort_with_message(ctx, "abort!"); } -pub fn _llvm_eh_typeid_for(_ctx: &EmEnv, _type_info_addr: u32) -> i32 { +pub fn _llvm_eh_typeid_for(_ctx: ContextMut<'_, EmEnv>, _type_info_addr: u32) -> i32 { debug!("emscripten::_llvm_eh_typeid_for"); -1 } -pub fn _system(_ctx: &EmEnv, _one: i32) -> c_int { +pub fn _system(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> c_int { debug!("emscripten::_system"); // TODO: May need to change this Em impl to a working version eprintln!("Can't call external programs"); EAGAIN } -pub fn _popen(_ctx: &EmEnv, _one: i32, _two: i32) -> c_int { +pub fn _popen(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> c_int { debug!("emscripten::_popen"); // TODO: May need to change this Em impl to a working version eprintln!("Missing function: popen"); diff --git a/lib/emscripten/src/pthread.rs b/lib/emscripten/src/pthread.rs index c4ab3d6b137..2ffd17c97a0 100644 --- a/lib/emscripten/src/pthread.rs +++ b/lib/emscripten/src/pthread.rs @@ -1,11 +1,17 @@ use crate::EmEnv; +use wasmer::ContextMut; -pub fn _pthread_attr_destroy(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_attr_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_attr_destroy"); 0 } -pub fn _pthread_attr_getstack(_ctx: &EmEnv, _stackaddr: i32, _stacksize: i32, _other: i32) -> i32 { +pub fn _pthread_attr_getstack( + mut _ctx: ContextMut<'_, EmEnv>, + _stackaddr: i32, + _stacksize: i32, + _other: i32, +) -> i32 { trace!( "emscripten::_pthread_attr_getstack({}, {}, {})", _stackaddr, @@ -18,175 +24,175 @@ pub fn _pthread_attr_getstack(_ctx: &EmEnv, _stackaddr: i32, _stacksize: i32, _o 0 } -pub fn _pthread_attr_init(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_attr_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_attr_init({})", _a); 0 } -pub fn _pthread_attr_setstacksize(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_attr_setstacksize(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_attr_setstacksize"); 0 } -pub fn _pthread_cleanup_pop(_ctx: &EmEnv, _a: i32) { +pub fn _pthread_cleanup_pop(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) { trace!("emscripten::_pthread_cleanup_pop"); } -pub fn _pthread_cleanup_push(_ctx: &EmEnv, _a: i32, _b: i32) { +pub fn _pthread_cleanup_push(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) { trace!("emscripten::_pthread_cleanup_push"); } -pub fn _pthread_cond_destroy(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_cond_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_cond_destroy"); 0 } -pub fn _pthread_cond_init(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_cond_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_cond_init"); 0 } -pub fn _pthread_cond_signal(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_cond_signal(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_cond_signal"); 0 } -pub fn _pthread_cond_timedwait(_ctx: &EmEnv, _a: i32, _b: i32, _c: i32) -> i32 { +pub fn _pthread_cond_timedwait(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32) -> i32 { trace!("emscripten::_pthread_cond_timedwait"); 0 } -pub fn _pthread_cond_wait(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_cond_wait(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_cond_wait"); 0 } -pub fn _pthread_condattr_destroy(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_condattr_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_condattr_destroy"); 0 } -pub fn _pthread_condattr_init(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_condattr_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_condattr_init"); 0 } -pub fn _pthread_condattr_setclock(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_condattr_setclock(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_condattr_setclock"); 0 } -pub fn _pthread_create(_ctx: &EmEnv, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 { +pub fn _pthread_create(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 { trace!("emscripten::_pthread_create"); // 11 seems to mean "no" 11 } -pub fn _pthread_detach(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_detach(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_detach"); 0 } -pub fn _pthread_equal(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_equal(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_equal"); 0 } -pub fn _pthread_exit(_ctx: &EmEnv, _a: i32) { +pub fn _pthread_exit(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) { trace!("emscripten::_pthread_exit"); } -pub fn _pthread_getattr_np(_ctx: &EmEnv, _thread: i32, _attr: i32) -> i32 { +pub fn _pthread_getattr_np(mut _ctx: ContextMut<'_, EmEnv>, _thread: i32, _attr: i32) -> i32 { trace!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr); 0 } -pub fn _pthread_getspecific(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_getspecific(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_getspecific"); 0 } -pub fn _pthread_join(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_join(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_join"); 0 } -pub fn _pthread_self(_ctx: &EmEnv) -> i32 { +pub fn _pthread_self(mut _ctx: ContextMut<'_, EmEnv>) -> i32 { trace!("emscripten::_pthread_self"); 0 } -pub fn _pthread_key_create(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_key_create(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_key_create"); 0 } -pub fn _pthread_mutex_destroy(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_mutex_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_mutex_destroy"); 0 } -pub fn _pthread_mutex_init(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_mutex_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_mutex_init"); 0 } -pub fn _pthread_mutexattr_destroy(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_mutexattr_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_mutexattr_destroy"); 0 } -pub fn _pthread_mutexattr_init(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_mutexattr_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_mutexattr_init"); 0 } -pub fn _pthread_mutexattr_settype(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_mutexattr_settype(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_mutexattr_settype"); 0 } -pub fn _pthread_once(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_once(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_once"); 0 } -pub fn _pthread_rwlock_destroy(_ctx: &EmEnv, _rwlock: i32) -> i32 { +pub fn _pthread_rwlock_destroy(mut _ctx: ContextMut<'_, EmEnv>, _rwlock: i32) -> i32 { trace!("emscripten::_pthread_rwlock_destroy({})", _rwlock); 0 } -pub fn _pthread_rwlock_init(_ctx: &EmEnv, _rwlock: i32, _attr: i32) -> i32 { +pub fn _pthread_rwlock_init(mut _ctx: ContextMut<'_, EmEnv>, _rwlock: i32, _attr: i32) -> i32 { trace!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr); 0 } -pub fn _pthread_rwlock_rdlock(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_rwlock_rdlock(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_rwlock_rdlock"); 0 } -pub fn _pthread_rwlock_unlock(_ctx: &EmEnv, _a: i32) -> i32 { +pub fn _pthread_rwlock_unlock(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { trace!("emscripten::_pthread_rwlock_unlock"); 0 } -pub fn _pthread_rwlock_wrlock(_ctx: &EmEnv, _rwlock: i32) -> i32 { +pub fn _pthread_rwlock_wrlock(mut _ctx: ContextMut<'_, EmEnv>, _rwlock: i32) -> i32 { trace!("emscripten::_pthread_rwlock_wrlock({})", _rwlock); 0 } -pub fn _pthread_setcancelstate(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_setcancelstate(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_setcancelstate"); 0 } -pub fn _pthread_setspecific(_ctx: &EmEnv, _a: i32, _b: i32) -> i32 { +pub fn _pthread_setspecific(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_setspecific"); 0 } -pub fn _pthread_sigmask(_ctx: &EmEnv, _a: i32, _b: i32, _c: i32) -> i32 { +pub fn _pthread_sigmask(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32) -> i32 { trace!("emscripten::_pthread_sigmask"); 0 } diff --git a/lib/emscripten/src/signal.rs b/lib/emscripten/src/signal.rs index 34fd22416b2..1e0c55f9b5a 100644 --- a/lib/emscripten/src/signal.rs +++ b/lib/emscripten/src/signal.rs @@ -1,47 +1,48 @@ // use super::varargs::VarArgs; use crate::EmEnv; +use wasmer::ContextMut; #[allow(clippy::cast_ptr_alignment)] -pub fn _sigemptyset(ctx: &EmEnv, set: u32) -> i32 { +pub fn _sigemptyset(ctx: ContextMut<'_, EmEnv>, set: u32) -> i32 { debug!("emscripten::_sigemptyset"); - let set_addr = emscripten_memory_pointer!(ctx.memory(0), set) as *mut u32; + let set_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), set) as *mut u32; unsafe { *set_addr = 0; } 0 } -pub fn _sigaction(_ctx: &EmEnv, _signum: u32, _act: u32, _oldact: u32) -> i32 { +pub fn _sigaction(_ctx: ContextMut<'_, EmEnv>, _signum: u32, _act: u32, _oldact: u32) -> i32 { debug!("emscripten::_sigaction {}, {}, {}", _signum, _act, _oldact); 0 } -pub fn _siginterrupt(_ctx: &EmEnv, _a: u32, _b: u32) -> i32 { +pub fn _siginterrupt(_ctx: ContextMut<'_, EmEnv>, _a: u32, _b: u32) -> i32 { debug!("emscripten::_siginterrupt {}, {}", _a, _b); 0 } #[allow(clippy::cast_ptr_alignment)] -pub fn _sigaddset(ctx: &EmEnv, set: u32, signum: u32) -> i32 { +pub fn _sigaddset(ctx: ContextMut<'_, EmEnv>, set: u32, signum: u32) -> i32 { debug!("emscripten::_sigaddset {}, {}", set, signum); - let set_addr = emscripten_memory_pointer!(ctx.memory(0), set) as *mut u32; + let set_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), set) as *mut u32; unsafe { *set_addr |= 1 << (signum - 1); } 0 } -pub fn _sigsuspend(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _sigsuspend(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_sigsuspend"); -1 } -pub fn _sigprocmask(_ctx: &EmEnv, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _sigprocmask(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_sigprocmask"); 0 } -pub fn _signal(_ctx: &EmEnv, _sig: u32, _two: i32) -> i32 { +pub fn _signal(_ctx: ContextMut<'_, EmEnv>, _sig: u32, _two: i32) -> i32 { debug!("emscripten::_signal ({})", _sig); 0 } diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index b050b1b1f92..6b8dc0ffd47 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -48,54 +48,54 @@ use super::env; #[allow(unused_imports)] use std::io::Error; use std::slice; -use wasmer::WasmPtr; +use wasmer::{AsContextMut, ContextMut, WasmPtr}; /// exit -pub fn ___syscall1(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) { +pub fn ___syscall1(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) { debug!("emscripten::___syscall1 (exit) {}", _which); - let status: i32 = varargs.get(ctx); + let status: i32 = varargs.get(&ctx); unsafe { exit(status); } } /// read -pub fn ___syscall3(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall3(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall3 (read) {}", _which); - let fd: i32 = varargs.get(ctx); - let buf: u32 = varargs.get(ctx); - let count: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let buf: u32 = varargs.get(&ctx); + let count: i32 = varargs.get(&ctx); debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count); - let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void; + let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut c_void; let ret = unsafe { read(fd, buf_addr, count as _) }; debug!("=> ret: {}", ret); ret as _ } /// write -pub fn ___syscall4(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall4(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall4 (write) {}", _which); - let fd: i32 = varargs.get(ctx); - let buf: i32 = varargs.get(ctx); - let count: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let buf: i32 = varargs.get(&ctx); + let count: i32 = varargs.get(&ctx); debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count); - let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void; + let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *const c_void; unsafe { write(fd, buf_addr, count as _) as i32 } } /// close -pub fn ___syscall6(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall6(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall6 (close) {}", _which); - let fd: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); debug!("fd: {}", fd); unsafe { close(fd) } } // chdir -pub fn ___syscall12(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall12(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall12 (chdir) {}", _which); - let path_ptr = varargs.get_str(ctx); + let path_ptr = varargs.get_str(&ctx); let real_path_owned = get_cstr_path(ctx, path_ptr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() @@ -111,63 +111,63 @@ pub fn ___syscall12(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { ret } -pub fn ___syscall10(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall10(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall10"); -1 } -pub fn ___syscall14(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall14(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall14"); -1 } -pub fn ___syscall15(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall15(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall15"); -1 } // getpid -pub fn ___syscall20(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall20(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall20 (getpid)"); unsafe { getpid() } } -pub fn ___syscall21(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall21(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall21"); -1 } -pub fn ___syscall25(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall25(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall25"); -1 } -pub fn ___syscall29(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall29(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall29"); -1 } -pub fn ___syscall32(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall32(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall32"); -1 } -pub fn ___syscall33(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall33(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall33"); -1 } -pub fn ___syscall36(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall36(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall36"); -1 } // rename -pub fn ___syscall38(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall38(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall38 (rename)"); - let old_path = varargs.get_str(ctx); - let new_path = varargs.get_str(ctx); - let real_old_path_owned = get_cstr_path(ctx, old_path as *const _); + let old_path = varargs.get_str(&ctx); + let new_path = varargs.get_str(&ctx); + let real_old_path_owned = get_cstr_path(ctx.as_context_mut(), old_path as *const _); let real_old_path = if let Some(ref rp) = real_old_path_owned { rp.as_c_str().as_ptr() } else { @@ -190,9 +190,9 @@ pub fn ___syscall38(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { } // rmdir -pub fn ___syscall40(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall40(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall40 (rmdir)"); - let pathname_addr = varargs.get_str(ctx); + let pathname_addr = varargs.get_str(&ctx); let real_path_owned = get_cstr_path(ctx, pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() @@ -203,16 +203,16 @@ pub fn ___syscall40(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { } // pipe -pub fn ___syscall42(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall42(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall42 (pipe)"); // offset to a file descriptor, which contains a read end and write end, 2 integers - let fd_offset: u32 = varargs.get(ctx); + let fd_offset: u32 = varargs.get(&ctx); - let emscripten_memory = ctx.memory(0); + let emscripten_memory = ctx.data().memory(0); // convert the file descriptor into a vec with two slots let mut fd_vec: [c_int; 2] = WasmPtr::<[c_int; 2]>::new(fd_offset) - .deref(&emscripten_memory) + .deref(&ctx, &emscripten_memory) .read() .unwrap(); @@ -230,133 +230,133 @@ pub fn ___syscall42(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { result } -pub fn ___syscall51(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall51(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall51"); -1 } -pub fn ___syscall52(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall52(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall52"); -1 } -pub fn ___syscall53(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall53(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall53"); -1 } -pub fn ___syscall60(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall60(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall60"); -1 } // dup2 -pub fn ___syscall63(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall63(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall63 (dup2) {}", _which); - let src: i32 = varargs.get(ctx); - let dst: i32 = varargs.get(ctx); + let src: i32 = varargs.get(&ctx); + let dst: i32 = varargs.get(&ctx); unsafe { dup2(src, dst) } } // getppid -pub fn ___syscall64(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall64(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall64 (getppid)"); unsafe { getpid() } } -pub fn ___syscall66(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall66(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall66"); -1 } -pub fn ___syscall75(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall75(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall75"); -1 } -pub fn ___syscall91(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall91(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall91 - stub"); 0 } -pub fn ___syscall96(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall96(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall96"); -1 } -pub fn ___syscall97(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall97(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall97"); -1 } -pub fn ___syscall110(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall110(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall110"); -1 } -pub fn ___syscall121(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall121(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall121"); -1 } -pub fn ___syscall125(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall125(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall125"); -1 } -pub fn ___syscall133(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall133(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall133"); -1 } -pub fn ___syscall144(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall144(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall144"); -1 } -pub fn ___syscall147(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall147(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall147"); -1 } -pub fn ___syscall150(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall150(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall150"); -1 } -pub fn ___syscall151(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall151(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall151"); -1 } -pub fn ___syscall152(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall152(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall152"); -1 } -pub fn ___syscall153(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall153(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall153"); -1 } -pub fn ___syscall163(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall163(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall163"); -1 } // getcwd -pub fn ___syscall183(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall183(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall183"); - let buf_offset: WasmPtr = varargs.get(ctx); - let _size: c_int = varargs.get(ctx); - let path = get_current_directory(ctx); + let buf_offset: WasmPtr = varargs.get(&ctx); + let _size: c_int = varargs.get(&ctx); + let path = get_current_directory(ctx.as_context_mut()); let path_string = path.unwrap().display().to_string(); let len = path_string.len(); - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); - let buf_writer = buf_offset.slice(&memory, len as u32 + 1).unwrap(); + let buf_writer = buf_offset.slice(&ctx, &memory, len as u32 + 1).unwrap(); for (i, byte) in path_string.bytes().enumerate() { buf_writer.index(i as u64).write(byte as _).unwrap(); } @@ -365,26 +365,26 @@ pub fn ___syscall183(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { } // mmap2 -pub fn ___syscall192(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall192(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall192 (mmap2) {}", _which); - let _addr: i32 = varargs.get(ctx); - let len: u32 = varargs.get(ctx); - let _prot: i32 = varargs.get(ctx); - let _flags: i32 = varargs.get(ctx); - let fd: i32 = varargs.get(ctx); - let _off: i32 = varargs.get(ctx); + let _addr: i32 = varargs.get(&ctx); + let len: u32 = varargs.get(&ctx); + let _prot: i32 = varargs.get(&ctx); + let _flags: i32 = varargs.get(&ctx); + let fd: i32 = varargs.get(&ctx); + let _off: i32 = varargs.get(&ctx); debug!( "=> addr: {}, len: {}, prot: {}, flags: {}, fd: {}, off: {}", _addr, len, _prot, _flags, fd, _off ); if fd == -1 { - let ptr = env::call_memalign(ctx, 16384, len); + let ptr = env::call_memalign(ctx.as_context_mut(), 16384, len); if ptr == 0 { // ENOMEM return -12; } - let real_ptr = emscripten_memory_pointer!(ctx.memory(0), ptr) as *const u8; + let real_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), ptr) as *const u8; env::call_memset(ctx, ptr, 0, len); for i in 0..(len as usize) { unsafe { @@ -400,19 +400,19 @@ pub fn ___syscall192(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } /// lseek -pub fn ___syscall140(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall140(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { // -> c_int debug!("emscripten::___syscall140 (lseek) {}", _which); - let fd: i32 = varargs.get(ctx); - let _offset_high: u32 = varargs.get(ctx); // We don't use the offset high as emscripten skips it - let offset_low: u32 = varargs.get(ctx); - let result_ptr_value: WasmPtr = varargs.get(ctx); - let whence: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let _offset_high: u32 = varargs.get(&ctx); // We don't use the offset high as emscripten skips it + let offset_low: u32 = varargs.get(&ctx); + let result_ptr_value: WasmPtr = varargs.get(&ctx); + let whence: i32 = varargs.get(&ctx); let offset = offset_low; let ret = unsafe { lseek(fd, offset as _, whence) as i64 }; - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); - let result_ptr = result_ptr_value.deref(&memory); + let result_ptr = result_ptr_value.deref(&ctx, &memory); result_ptr.write(ret).unwrap(); debug!( @@ -429,13 +429,13 @@ pub fn ___syscall140(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { /// readv #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall145(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall145(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall145 (readv) {}", _which); - let fd: i32 = varargs.get(ctx); - let iov: i32 = varargs.get(ctx); - let iovcnt: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let iov: i32 = varargs.get(&ctx); + let iovcnt: i32 = varargs.get(&ctx); #[repr(C)] struct GuestIovec { @@ -448,9 +448,11 @@ pub fn ___syscall145(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { unsafe { for i in 0..iovcnt { let guest_iov_addr = - emscripten_memory_pointer!(ctx.memory(0), (iov + i * 8)) as *mut GuestIovec; - let iov_base = emscripten_memory_pointer!(ctx.memory(0), (*guest_iov_addr).iov_base) - as *mut c_void; + emscripten_memory_pointer!(ctx, ctx.data().memory(0), (iov + i * 8)) + as *mut GuestIovec; + let iov_base = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), (*guest_iov_addr).iov_base) + as *mut c_void; let iov_len = (*guest_iov_addr).iov_len as _; // debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len); let curr = read(fd, iov_base, iov_len); @@ -466,12 +468,12 @@ pub fn ___syscall145(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { // writev #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall146(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall146(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall146 (writev) {}", _which); - let fd: i32 = varargs.get(ctx); - let iov: i32 = varargs.get(ctx); - let iovcnt: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let iov: i32 = varargs.get(&ctx); + let iovcnt: i32 = varargs.get(&ctx); #[repr(C)] struct GuestIovec { @@ -484,9 +486,11 @@ pub fn ___syscall146(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { for i in 0..iovcnt { unsafe { let guest_iov_addr = - emscripten_memory_pointer!(ctx.memory(0), (iov + i * 8)) as *mut GuestIovec; - let iov_base = emscripten_memory_pointer!(ctx.memory(0), (*guest_iov_addr).iov_base) - as *const c_void; + emscripten_memory_pointer!(ctx, ctx.data().memory(0), (iov + i * 8)) + as *mut GuestIovec; + let iov_base = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), (*guest_iov_addr).iov_base) + as *const c_void; let iov_len = (*guest_iov_addr).iov_len as _; // debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len); let curr = write(fd, iov_base, iov_len); @@ -507,14 +511,14 @@ pub fn ___syscall146(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { ret as _ } -pub fn ___syscall191(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { - let _resource: i32 = varargs.get(ctx); +pub fn ___syscall191(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { + let _resource: i32 = varargs.get(&ctx); debug!( "emscripten::___syscall191 - mostly stub, resource: {}", _resource ); - let rlim_emptr: i32 = varargs.get(ctx); - let rlim_ptr = emscripten_memory_pointer!(ctx.memory(0), rlim_emptr) as *mut u8; + let rlim_emptr: i32 = varargs.get(&ctx); + let rlim_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), rlim_emptr) as *mut u8; let rlim = unsafe { slice::from_raw_parts_mut(rlim_ptr, 16) }; // set all to RLIM_INIFINTY @@ -524,18 +528,18 @@ pub fn ___syscall191(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { 0 } -pub fn ___syscall193(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall193(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall193"); -1 } // stat64 -pub fn ___syscall195(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall195(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall195 (stat64) {}", _which); - let pathname_addr = varargs.get_str(ctx); - let buf: u32 = varargs.get(ctx); + let pathname_addr = varargs.get_str(&ctx); + let buf: u32 = varargs.get(&ctx); - let real_path_owned = get_cstr_path(ctx, pathname_addr as *const _); + let real_path_owned = get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -561,11 +565,11 @@ pub fn ___syscall195(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } // fstat64 -pub fn ___syscall197(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall197(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall197 (fstat64) {}", _which); - let fd: c_int = varargs.get(ctx); - let buf: u32 = varargs.get(ctx); + let fd: c_int = varargs.get(&ctx); + let buf: u32 = varargs.get(&ctx); unsafe { let mut stat = std::mem::zeroed(); @@ -580,135 +584,135 @@ pub fn ___syscall197(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int 0 } -pub fn ___syscall209(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall209(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall209"); -1 } -pub fn ___syscall211(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall211(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall211"); -1 } -pub fn ___syscall218(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall218(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall218"); -1 } -pub fn ___syscall268(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall268(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall268"); -1 } -pub fn ___syscall269(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall269(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall269"); -1 } -pub fn ___syscall272(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall272(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall272"); -1 } -pub fn ___syscall295(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall295(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall295"); -1 } -pub fn ___syscall296(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall296(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall296"); -1 } -pub fn ___syscall297(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall297(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall297"); -1 } -pub fn ___syscall298(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall298(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall298"); -1 } -pub fn ___syscall300(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall300(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall300"); -1 } -pub fn ___syscall301(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall301(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall301"); -1 } -pub fn ___syscall302(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall302(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall302"); -1 } -pub fn ___syscall303(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall303(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall303"); -1 } -pub fn ___syscall304(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall304(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall304"); -1 } -pub fn ___syscall305(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall305(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall305"); -1 } -pub fn ___syscall306(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall306(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall306"); -1 } -pub fn ___syscall307(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall307(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall307"); -1 } -pub fn ___syscall308(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall308(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall308"); -1 } // utimensat -pub fn ___syscall320(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall320(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall320 (utimensat), {}", _which); 0 } -pub fn ___syscall331(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall331(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall331"); -1 } -pub fn ___syscall333(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall333(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall333"); -1 } -pub fn ___syscall334(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall334(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall334"); -1 } -pub fn ___syscall337(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall337(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall337"); -1 } // prlimit64 -pub fn ___syscall340(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall340(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall340 (prlimit64), {}", _which); // NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway. - let _pid: i32 = varargs.get(ctx); - let resource: i32 = varargs.get(ctx); - let _new_limit: u32 = varargs.get(ctx); - let old_limit: u32 = varargs.get(ctx); + let _pid: i32 = varargs.get(&ctx); + let resource: i32 = varargs.get(&ctx); + let _new_limit: u32 = varargs.get(&ctx); + let old_limit: u32 = varargs.get(&ctx); let val = match resource { // RLIMIT_NOFILE @@ -718,7 +722,7 @@ pub fn ___syscall340(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int if old_limit != 0 { // just report no limits - let buf_ptr = emscripten_memory_pointer!(ctx.memory(0), old_limit) as *mut u8; + let buf_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), old_limit) as *mut u8; let buf = unsafe { slice::from_raw_parts_mut(buf_ptr, 16) }; LittleEndian::write_i64(&mut *buf, val); @@ -728,7 +732,7 @@ pub fn ___syscall340(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int 0 } -pub fn ___syscall345(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall345(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall345"); -1 } diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 20518b052e3..109fb25d6c0 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -81,7 +81,7 @@ use libc::{ // TCGETS, // TCSETSW, }; -use wasmer::{ValueType, WasmPtr}; +use wasmer::{AsContextMut, ContextMut, ValueType, WasmPtr}; // They are not exposed in in Rust libc in macOS const TCGETS: u64 = 0x5401; @@ -157,12 +157,12 @@ use libc::SO_NOSIGPIPE; const SO_NOSIGPIPE: c_int = 0; /// open -pub fn ___syscall5(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall5(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall5 (open) {}", _which); - let pathname_addr = varargs.get_str(ctx); - let flags: i32 = varargs.get(ctx); - let mode: u32 = varargs.get(ctx); - let real_path_owned = utils::get_cstr_path(ctx, pathname_addr as *const _); + let pathname_addr = varargs.get_str(&ctx); + let flags: i32 = varargs.get(&ctx); + let mode: u32 = varargs.get(&ctx); + let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -181,11 +181,11 @@ pub fn ___syscall5(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { } /// link -pub fn ___syscall9(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall9(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall9 (link) {}", _which); - let oldname_ptr = varargs.get_str(ctx); - let newname_ptr = varargs.get_str(ctx); + let oldname_ptr = varargs.get_str(&ctx); + let newname_ptr = varargs.get_str(&ctx); let result = unsafe { link(oldname_ptr, newname_ptr) }; debug!( "=> oldname: {}, newname: {}, result: {}", @@ -197,30 +197,30 @@ pub fn ___syscall9(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { } /// getrusage -pub fn ___syscall77(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall77(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall77 (getrusage) {}", _which); - let resource: c_int = varargs.get(ctx); - let rusage_ptr: c_int = varargs.get(ctx); + let resource: c_int = varargs.get(&ctx); + let rusage_ptr: c_int = varargs.get(&ctx); #[allow(clippy::cast_ptr_alignment)] - let rusage = emscripten_memory_pointer!(ctx.memory(0), rusage_ptr) as *mut rusage; + let rusage = emscripten_memory_pointer!(ctx, ctx.data().memory(0), rusage_ptr) as *mut rusage; assert_eq!(8, mem::align_of_val(&rusage)); unsafe { getrusage(resource, rusage) } } /// symlink -pub fn ___syscall83(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall83(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall83 (symlink) {}", _which); - let path1 = varargs.get_str(ctx); - let path2 = varargs.get_str(ctx); - let real_path1_owned = utils::get_cstr_path(ctx, path1 as *const _); + let path1 = varargs.get_str(&ctx); + let path2 = varargs.get_str(&ctx); + let real_path1_owned = utils::get_cstr_path(ctx.as_context_mut(), path1 as *const _); let real_path1 = if let Some(ref rp) = real_path1_owned { rp.as_c_str().as_ptr() } else { path1 }; - let real_path2_owned = utils::get_cstr_path(ctx, path2 as *const _); + let real_path2_owned = utils::get_cstr_path(ctx.as_context_mut(), path2 as *const _); let real_path2 = if let Some(ref rp) = real_path2_owned { rp.as_c_str().as_ptr() } else { @@ -237,13 +237,13 @@ pub fn ___syscall83(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { } /// readlink -pub fn ___syscall85(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall85(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall85 (readlink)"); - let pathname_addr = varargs.get_str(ctx); - let buf = varargs.get_str(ctx); - // let buf_addr: i32 = varargs.get(ctx); - let buf_size: i32 = varargs.get(ctx); - let real_path_owned = get_cstr_path(ctx, pathname_addr as *const _); + let pathname_addr = varargs.get_str(&ctx); + let buf = varargs.get_str(&ctx); + // let buf_addr: i32 = varargs.get(&ctx); + let buf_size: i32 = varargs.get(&ctx); + let real_path_owned = get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -266,10 +266,10 @@ pub fn ___syscall85(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> i32 { } /// ftruncate64 -pub fn ___syscall194(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall194(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall194 (ftruncate64) {}", _which); - let _fd: c_int = varargs.get(ctx); - let _length: i64 = varargs.get(ctx); + let _fd: c_int = varargs.get(&ctx); + let _length: i64 = varargs.get(&ctx); #[cfg(not(any(target_os = "freebsd", target_vendor = "apple")))] unsafe { ftruncate64(_fd, _length) @@ -283,17 +283,17 @@ pub fn ___syscall194(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } /// lchown -pub fn ___syscall198(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall198(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall198 (lchown) {}", _which); - let path_ptr = varargs.get_str(ctx); - let real_path_owned = utils::get_cstr_path(ctx, path_ptr as *const _); + let path_ptr = varargs.get_str(&ctx); + let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), path_ptr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { path_ptr }; - let uid: uid_t = varargs.get(ctx); - let gid: gid_t = varargs.get(ctx); + let uid: uid_t = varargs.get(&ctx); + let gid: gid_t = varargs.get(&ctx); let result = unsafe { lchown(real_path, uid, gid) }; debug!( "=> path: {}, uid: {}, gid: {}, result: {}", @@ -306,13 +306,13 @@ pub fn ___syscall198(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } /// getgroups -pub fn ___syscall205(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall205(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall205 (getgroups) {}", _which); - let ngroups_max: c_int = varargs.get(ctx); - let groups: c_int = varargs.get(ctx); + let ngroups_max: c_int = varargs.get(&ctx); + let groups: c_int = varargs.get(&ctx); #[allow(clippy::cast_ptr_alignment)] - let gid_ptr = emscripten_memory_pointer!(ctx.memory(0), groups) as *mut gid_t; + let gid_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), groups) as *mut gid_t; assert_eq!(4, mem::align_of_val(&gid_ptr)); let result = unsafe { getgroups(ngroups_max, gid_ptr) }; debug!( @@ -323,46 +323,46 @@ pub fn ___syscall205(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } // chown -pub fn ___syscall212(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall212(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); - let pathname_addr = varargs.get_str(ctx); - let real_path_owned = utils::get_cstr_path(ctx, pathname_addr as *const _); + let pathname_addr = varargs.get_str(&ctx); + let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { pathname_addr }; - let owner: u32 = varargs.get(ctx); - let group: u32 = varargs.get(ctx); + let owner: u32 = varargs.get(&ctx); + let group: u32 = varargs.get(&ctx); unsafe { chown(real_path, owner, group) } } /// madvise -pub fn ___syscall219(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall219(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); - let addr_ptr: c_int = varargs.get(ctx); - let len: usize = varargs.get(ctx); - let advice: c_int = varargs.get(ctx); + let addr_ptr: c_int = varargs.get(&ctx); + let len: usize = varargs.get(&ctx); + let advice: c_int = varargs.get(&ctx); - let addr = emscripten_memory_pointer!(ctx.memory(0), addr_ptr) as *mut c_void; + let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), addr_ptr) as *mut c_void; unsafe { madvise(addr, len, advice) } } /// access -pub fn ___syscall33(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall33(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall33 (access) {}", _which); - let path = varargs.get_str(ctx); - let real_path_owned = utils::get_cstr_path(ctx, path as *const _); + let path = varargs.get_str(&ctx); + let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), path as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { path }; - let amode: c_int = varargs.get(ctx); + let amode: c_int = varargs.get(&ctx); let result = unsafe { access(real_path, amode) }; debug!( "=> path: {}, amode: {}, result: {}", @@ -374,41 +374,41 @@ pub fn ___syscall33(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { } /// nice -pub fn ___syscall34(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall34(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall34 (nice) {}", _which); - let inc_r: c_int = varargs.get(ctx); + let inc_r: c_int = varargs.get(&ctx); unsafe { nice(inc_r) } } // mkdir -pub fn ___syscall39(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall39(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", _which); - let pathname_addr = varargs.get_str(ctx); - let real_path_owned = utils::get_cstr_path(ctx, pathname_addr as *const _); + let pathname_addr = varargs.get_str(&ctx); + let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { pathname_addr }; - let mode: u32 = varargs.get(ctx); + let mode: u32 = varargs.get(&ctx); unsafe { mkdir(real_path, mode as _) } } /// dup -pub fn ___syscall41(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall41(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall41 (dup) {}", _which); - let fd: c_int = varargs.get(ctx); + let fd: c_int = varargs.get(&ctx); unsafe { dup(fd) } } /// getgid32 -pub fn ___syscall200(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall200(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall200 (getgid32)"); unsafe { getgid() as i32 } } // geteuid32 -pub fn ___syscall201(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall201(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (geteuid32)"); unsafe { // Maybe fix: Emscripten returns 0 always @@ -417,7 +417,7 @@ pub fn ___syscall201(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { } // getegid32 -pub fn ___syscall202(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall202(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { // gid_t debug!("emscripten::___syscall202 (getegid32)"); unsafe { @@ -427,21 +427,21 @@ pub fn ___syscall202(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { } /// fchown -pub fn ___syscall207(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall207(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall207 (fchown) {}", _which); - let fd: c_int = varargs.get(ctx); - let owner: uid_t = varargs.get(ctx); - let group: gid_t = varargs.get(ctx); + let fd: c_int = varargs.get(&ctx); + let owner: uid_t = varargs.get(&ctx); + let group: gid_t = varargs.get(&ctx); unsafe { fchown(fd, owner, group) } } /// dup3 -pub fn ___syscall330(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> pid_t { +pub fn ___syscall330(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> pid_t { // Implementation based on description at https://linux.die.net/man/2/dup3 debug!("emscripten::___syscall330 (dup3)"); - let oldfd: c_int = varargs.get(ctx); - let newfd: c_int = varargs.get(ctx); - let flags: c_int = varargs.get(ctx); + let oldfd: c_int = varargs.get(&ctx); + let newfd: c_int = varargs.get(&ctx); + let flags: c_int = varargs.get(&ctx); if oldfd == newfd { return EINVAL; @@ -474,19 +474,20 @@ pub fn ___syscall330(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> pid_t } /// ioctl -pub fn ___syscall54(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall54(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall54 (ioctl) {}", _which); - let fd: i32 = varargs.get(ctx); - let request: u32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let request: u32 = varargs.get(&ctx); debug!("=> fd: {}, op: {}", fd, request); // Got the equivalents here: https://code.woboq.org/linux/linux/include/uapi/asm-generic/ioctls.h.html match request { WASM_FIOCLEX | WASM_FIONBIO | WASM_TIOCGWINSZ | WASM_TIOCSPGRP | WASM_TCGETS | WASM_TCSETSW => { - let argp: u32 = varargs.get(ctx); - let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void; + let argp: u32 = varargs.get(&ctx); + let argp_ptr = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), argp) as *mut c_void; let translated_request = translate_ioctl(request); let ret = unsafe { ioctl(fd, translated_request as _, argp_ptr) }; debug!( @@ -516,11 +517,11 @@ const SOCK_CLOEXC: i32 = 0x80000; // socketcall #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall102(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall102 (socketcall) {}", _which); - let call: u32 = varargs.get(ctx); - let mut socket_varargs: VarArgs = varargs.get(ctx); - let memory = ctx.memory(0); + let call: u32 = varargs.get(&ctx); + let mut socket_varargs: VarArgs = varargs.get(&ctx); + let memory = ctx.data().memory(0); // migrating to EmSockAddr, port being separate here is nice, should update that too #[repr(C)] @@ -541,9 +542,9 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int 1 => { debug!("socket: socket"); // socket (domain: c_int, ty: c_int, protocol: c_int) -> c_int - let domain: i32 = socket_varargs.get(ctx); - let ty_and_flags: i32 = socket_varargs.get(ctx); - let protocol: i32 = socket_varargs.get(ctx); + let domain: i32 = socket_varargs.get(&ctx); + let ty_and_flags: i32 = socket_varargs.get(&ctx); + let protocol: i32 = socket_varargs.get(&ctx); let ty = ty_and_flags & (!SOCK_NON_BLOCK) & (!SOCK_CLOEXC); let fd = unsafe { socket(domain, ty, protocol) }; @@ -582,10 +583,10 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int debug!("socket: bind"); // bind (socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int // TODO: Emscripten has a different signature. - let socket = socket_varargs.get(ctx); - let address: u32 = socket_varargs.get(ctx); - let address_len = socket_varargs.get(ctx); - let address = emscripten_memory_pointer!(&memory, address) as *mut sockaddr; + let socket = socket_varargs.get(&ctx); + let address: u32 = socket_varargs.get(&ctx); + let address_len = socket_varargs.get(&ctx); + let address = emscripten_memory_pointer!(ctx, &memory, address) as *mut sockaddr; // Debug received address let _proper_address = address as *const GuestSockaddrIn; @@ -607,17 +608,17 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int debug!("socket: connect"); // connect (socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int // TODO: Emscripten has a different signature. - let socket = socket_varargs.get(ctx); - let address: u32 = socket_varargs.get(ctx); - let address_len = socket_varargs.get(ctx); - let address = emscripten_memory_pointer!(&memory, address) as *mut sockaddr; + let socket = socket_varargs.get(&ctx); + let address: u32 = socket_varargs.get(&ctx); + let address_len = socket_varargs.get(&ctx); + let address = emscripten_memory_pointer!(ctx, &memory, address) as *mut sockaddr; unsafe { connect(socket, address, address_len) } } 4 => { debug!("socket: listen"); // listen (socket: c_int, backlog: c_int) -> c_int - let socket = socket_varargs.get(ctx); - let backlog: i32 = socket_varargs.get(ctx); + let socket = socket_varargs.get(&ctx); + let backlog: i32 = socket_varargs.get(&ctx); let status = unsafe { listen(socket, backlog) }; debug!( "=> socketfd: {}, backlog: {} = status: {}", @@ -628,17 +629,17 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int 5 => { debug!("socket: accept"); // accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int - let socket: i32 = socket_varargs.get(ctx); - let address: WasmPtr = socket_varargs.get(ctx); - let address_len: WasmPtr = socket_varargs.get(ctx); + let socket: i32 = socket_varargs.get(&ctx); + let address: WasmPtr = socket_varargs.get(&ctx); + let address_len: WasmPtr = socket_varargs.get(&ctx); debug!( "=> socket: {}, address: {:?}, address_len: {}", socket, - address.deref(&memory).read().unwrap(), - address_len.deref(&memory).read().unwrap() + address.deref(&ctx, &memory).read().unwrap(), + address_len.deref(&ctx, &memory).read().unwrap() ); - let mut address_len_addr = address_len.deref(&memory).read().unwrap(); + let mut address_len_addr = address_len.deref(&ctx, &memory).read().unwrap(); // let mut address_len_addr: socklen_t = 0; let mut host_address: sockaddr = sockaddr { @@ -648,7 +649,7 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int sa_len: Default::default(), }; let fd = unsafe { accept(socket, &mut host_address, &mut address_len_addr) }; - let mut address_addr = address.deref(&memory).read().unwrap(); + let mut address_addr = address.deref(&ctx, &memory).read().unwrap(); address_addr.sa_family = host_address.sa_family as _; address_addr.sa_data = host_address.sa_data; @@ -669,10 +670,10 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int 6 => { debug!("socket: getsockname"); // getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int - let socket: i32 = socket_varargs.get(ctx); - let address: WasmPtr = socket_varargs.get(ctx); - let address_len: WasmPtr = socket_varargs.get(ctx); - let address_len_addr = address_len.deref(&memory).read().unwrap(); + let socket: i32 = socket_varargs.get(&ctx); + let address: WasmPtr = socket_varargs.get(&ctx); + let address_len: WasmPtr = socket_varargs.get(&ctx); + let address_len_addr = address_len.deref(&ctx, &memory).read().unwrap(); let mut sock_addr_host: sockaddr = sockaddr { sa_family: Default::default(), @@ -688,7 +689,7 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int ) }; // translate from host data into emscripten data - let mut address_mut = address.deref(&memory).read().unwrap(); + let mut address_mut = address.deref(&ctx, &memory).read().unwrap(); address_mut.sa_family = sock_addr_host.sa_family as _; address_mut.sa_data = sock_addr_host.sa_data; @@ -702,40 +703,40 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int 7 => { debug!("socket: getpeername"); // getpeername (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int - let socket = socket_varargs.get(ctx); - let address: u32 = socket_varargs.get(ctx); - let address_len: u32 = socket_varargs.get(ctx); - let address = emscripten_memory_pointer!(memory, address) as *mut sockaddr; + let socket = socket_varargs.get(&ctx); + let address: u32 = socket_varargs.get(&ctx); + let address_len: u32 = socket_varargs.get(&ctx); + let address = emscripten_memory_pointer!(ctx, memory, address) as *mut sockaddr; let address_len_addr = - emscripten_memory_pointer!(memory, address_len) as *mut socklen_t; + emscripten_memory_pointer!(ctx, memory, address_len) as *mut socklen_t; unsafe { getpeername(socket, address, address_len_addr) } } 11 => { debug!("socket: sendto"); // sendto (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t - let socket = socket_varargs.get(ctx); - let buf: u32 = socket_varargs.get(ctx); - let flags = socket_varargs.get(ctx); - let len: i32 = socket_varargs.get(ctx); - let address: u32 = socket_varargs.get(ctx); - let address_len = socket_varargs.get(ctx); - let buf_addr = emscripten_memory_pointer!(memory, buf) as _; - let address = emscripten_memory_pointer!(memory, address) as *mut sockaddr; + let socket = socket_varargs.get(&ctx); + let buf: u32 = socket_varargs.get(&ctx); + let flags = socket_varargs.get(&ctx); + let len: i32 = socket_varargs.get(&ctx); + let address: u32 = socket_varargs.get(&ctx); + let address_len = socket_varargs.get(&ctx); + let buf_addr = emscripten_memory_pointer!(ctx, memory, buf) as _; + let address = emscripten_memory_pointer!(ctx, memory, address) as *mut sockaddr; unsafe { sendto(socket, buf_addr, flags, len, address, address_len) as i32 } } 12 => { debug!("socket: recvfrom"); // recvfrom (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t - let socket = socket_varargs.get(ctx); - let buf: u32 = socket_varargs.get(ctx); - let len: i32 = socket_varargs.get(ctx); - let flags: i32 = socket_varargs.get(ctx); - let address: u32 = socket_varargs.get(ctx); - let address_len: u32 = socket_varargs.get(ctx); - let buf_addr = emscripten_memory_pointer!(memory, buf) as _; - let address = emscripten_memory_pointer!(memory, address) as *mut sockaddr; + let socket = socket_varargs.get(&ctx); + let buf: u32 = socket_varargs.get(&ctx); + let len: i32 = socket_varargs.get(&ctx); + let flags: i32 = socket_varargs.get(&ctx); + let address: u32 = socket_varargs.get(&ctx); + let address_len: u32 = socket_varargs.get(&ctx); + let buf_addr = emscripten_memory_pointer!(ctx, memory, buf) as _; + let address = emscripten_memory_pointer!(ctx, memory, address) as *mut sockaddr; let address_len_addr = - emscripten_memory_pointer!(memory, address_len) as *mut socklen_t; + emscripten_memory_pointer!(ctx, memory, address_len) as *mut socklen_t; unsafe { recvfrom( socket, @@ -753,13 +754,13 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int // https://github.com/openbsd/src/blob/master/sys/sys/socket.h#L156 // setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int - let socket = socket_varargs.get(ctx); - let level: i32 = socket_varargs.get(ctx); + let socket = socket_varargs.get(&ctx); + let level: i32 = socket_varargs.get(&ctx); let level = if level == 1 { SOL_SOCKET } else { level }; - let untranslated_name: i32 = socket_varargs.get(ctx); - let value: u32 = socket_varargs.get(ctx); - let option_len: u32 = socket_varargs.get(ctx); - let value_addr = emscripten_memory_pointer!(memory, value) as *const libc::c_void; + let untranslated_name: i32 = socket_varargs.get(&ctx); + let value: u32 = socket_varargs.get(&ctx); + let option_len: u32 = socket_varargs.get(&ctx); + let value_addr = emscripten_memory_pointer!(ctx, memory, value) as *const libc::c_void; let name: i32 = translate_socket_name_flag(untranslated_name); let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) }; @@ -770,33 +771,34 @@ pub fn ___syscall102(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int 15 => { debug!("socket: getsockopt"); // getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int - let socket = socket_varargs.get(ctx); - let level: i32 = socket_varargs.get(ctx); + let socket = socket_varargs.get(&ctx); + let level: i32 = socket_varargs.get(&ctx); let level = if level == 1 { SOL_SOCKET } else { level }; - let untranslated_name: i32 = socket_varargs.get(ctx); + let untranslated_name: i32 = socket_varargs.get(&ctx); let name: i32 = translate_socket_name_flag(untranslated_name); - let value: u32 = socket_varargs.get(ctx); - let option_len: u32 = socket_varargs.get(ctx); - let value_addr = emscripten_memory_pointer!(memory, value) as _; - let option_len_addr = emscripten_memory_pointer!(memory, option_len) as *mut socklen_t; + let value: u32 = socket_varargs.get(&ctx); + let option_len: u32 = socket_varargs.get(&ctx); + let value_addr = emscripten_memory_pointer!(ctx, memory, value) as _; + let option_len_addr = + emscripten_memory_pointer!(ctx, memory, option_len) as *mut socklen_t; unsafe { getsockopt(socket, level, name, value_addr, option_len_addr) } } 16 => { debug!("socket: sendmsg"); // sendmsg (fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t - let socket: i32 = socket_varargs.get(ctx); - let msg: u32 = socket_varargs.get(ctx); - let flags: i32 = socket_varargs.get(ctx); - let msg_addr = emscripten_memory_pointer!(memory, msg) as *const msghdr; + let socket: i32 = socket_varargs.get(&ctx); + let msg: u32 = socket_varargs.get(&ctx); + let flags: i32 = socket_varargs.get(&ctx); + let msg_addr = emscripten_memory_pointer!(ctx, memory, msg) as *const msghdr; unsafe { sendmsg(socket, msg_addr, flags) as i32 } } 17 => { debug!("socket: recvmsg"); // recvmsg (fd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t - let socket: i32 = socket_varargs.get(ctx); - let msg: u32 = socket_varargs.get(ctx); - let flags: i32 = socket_varargs.get(ctx); - let msg_addr = emscripten_memory_pointer!(memory, msg) as *mut msghdr; + let socket: i32 = socket_varargs.get(&ctx); + let msg: u32 = socket_varargs.get(&ctx); + let flags: i32 = socket_varargs.get(&ctx); + let msg_addr = emscripten_memory_pointer!(ctx, memory, msg) as *mut msghdr; unsafe { recvmsg(socket, msg_addr, flags) as i32 } } _ => { @@ -831,10 +833,10 @@ fn translate_socket_name_flag(name: i32) -> i32 { } /// getpgid -pub fn ___syscall132(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall132(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall132 (getpgid)"); - let pid: pid_t = varargs.get(ctx); + let pid: pid_t = varargs.get(&ctx); let ret = unsafe { getpgid(pid) }; debug!("=> pid: {} = {}", pid, ret); @@ -853,14 +855,14 @@ pub struct EmPollFd { } /// poll -pub fn ___syscall168(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall168(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall168(poll)"); - let fds: WasmPtr = varargs.get(ctx); - let nfds: u32 = varargs.get(ctx); - let timeout: i32 = varargs.get(ctx); - let memory = ctx.memory(0); + let fds: WasmPtr = varargs.get(&ctx); + let nfds: u32 = varargs.get(&ctx); + let timeout: i32 = varargs.get(&ctx); + let memory = ctx.data().memory(0); - let mut fds_mut = fds.deref(&memory).read().unwrap(); + let mut fds_mut = fds.deref(&ctx, &memory).read().unwrap(); unsafe { libc::poll( @@ -872,35 +874,35 @@ pub fn ___syscall168(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { } // pread -pub fn ___syscall180(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall180(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", _which); - let fd: i32 = varargs.get(ctx); - let buf: u32 = varargs.get(ctx); - let count: u32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let buf: u32 = varargs.get(&ctx); + let count: u32 = varargs.get(&ctx); { - let zero: u32 = varargs.get(ctx); + let zero: u32 = varargs.get(&ctx); assert_eq!(zero, 0); } - let offset: i64 = varargs.get(ctx); + let offset: i64 = varargs.get(&ctx); - let buf_ptr = emscripten_memory_pointer!(ctx.memory(0), buf) as _; + let buf_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as _; unsafe { pread(fd, buf_ptr, count as _, offset) as _ } } // pwrite -pub fn ___syscall181(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall181(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall181 (pwrite) {}", _which); - let fd: i32 = varargs.get(ctx); - let buf: u32 = varargs.get(ctx); - let count: u32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let buf: u32 = varargs.get(&ctx); + let count: u32 = varargs.get(&ctx); { - let zero: u32 = varargs.get(ctx); + let zero: u32 = varargs.get(&ctx); assert_eq!(zero, 0); } - let offset: i64 = varargs.get(ctx); + let offset: i64 = varargs.get(&ctx); - let buf_ptr = emscripten_memory_pointer!(ctx.memory(0), buf) as _; + let buf_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as _; let status = unsafe { pwrite(fd, buf_ptr, count as _, offset) as _ }; debug!( "=> fd: {}, buf: {}, count: {}, offset: {} = status:{}", @@ -910,24 +912,24 @@ pub fn ___syscall181(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } /// fchmod -pub fn ___syscall94(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall94(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fchmod) {}", _which); - let fd: c_int = varargs.get(ctx); - let mode: mode_t = varargs.get(ctx); + let fd: c_int = varargs.get(&ctx); + let mode: mode_t = varargs.get(&ctx); unsafe { fchmod(fd, mode) } } /// wait4 #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall114(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> pid_t { +pub fn ___syscall114(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall114 (wait4)"); - let pid: pid_t = varargs.get(ctx); - let status: u32 = varargs.get(ctx); - let options: c_int = varargs.get(ctx); - let rusage: u32 = varargs.get(ctx); - let status_addr = emscripten_memory_pointer!(ctx.memory(0), status) as *mut c_int; + let pid: pid_t = varargs.get(&ctx); + let status: u32 = varargs.get(&ctx); + let options: c_int = varargs.get(&ctx); + let rusage: u32 = varargs.get(&ctx); + let status_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), status) as *mut c_int; - let rusage_addr = emscripten_memory_pointer!(ctx.memory(0), rusage) as *mut rusage; + let rusage_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), rusage) as *mut rusage; let res = unsafe { wait4(pid, status_addr, options, rusage_addr) }; debug!( "=> pid: {}, status: {:?}, options: {}, rusage: {:?} = pid: {}", @@ -937,22 +939,22 @@ pub fn ___syscall114(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> pid_t } /// fsync -pub fn ___syscall118(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall118(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fsync) {}", _which); - let fd: c_int = varargs.get(ctx); + let fd: c_int = varargs.get(&ctx); unsafe { fsync(fd) } } // select #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall142(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall142(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall142 (newselect) {}", _which); - let nfds: i32 = varargs.get(ctx); - let readfds: u32 = varargs.get(ctx); - let writefds: u32 = varargs.get(ctx); - let exceptfds: u32 = varargs.get(ctx); - let _timeout: i32 = varargs.get(ctx); + let nfds: i32 = varargs.get(&ctx); + let readfds: u32 = varargs.get(&ctx); + let writefds: u32 = varargs.get(&ctx); + let exceptfds: u32 = varargs.get(&ctx); + let _timeout: i32 = varargs.get(&ctx); if nfds > 1024 { // EINVAL @@ -960,27 +962,27 @@ pub fn ___syscall142(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } assert!(exceptfds == 0, "`exceptfds` is not supporrted"); - let readfds_ptr = emscripten_memory_pointer!(ctx.memory(0), readfds) as _; - let writefds_ptr = emscripten_memory_pointer!(ctx.memory(0), writefds) as _; + let readfds_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), readfds) as _; + let writefds_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), writefds) as _; unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) } } /// fdatasync -pub fn ___syscall148(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall148(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall148 (fdatasync) {}", _which); - let fd: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); unsafe { fdatasync(fd) } } // setpgid -pub fn ___syscall57(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall57(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall57 (setpgid) {}", _which); - let pid: i32 = varargs.get(ctx); - let pgid: i32 = varargs.get(ctx); + let pid: i32 = varargs.get(&ctx); + let pgid: i32 = varargs.get(&ctx); let ret = unsafe { setpgid(pid, pgid) }; debug!("=> pid: {}, pgid: {} = {}", pid, pgid, ret); @@ -992,25 +994,25 @@ pub fn ___syscall57(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall122(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall122 (uname) {}", _which); - let buf: u32 = varargs.get(ctx); + let buf: u32 = varargs.get(&ctx); debug!("=> buf: {}", buf); - let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut utsname; + let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut utsname; unsafe { uname(buf_addr) } } /// lstat64 -pub fn ___syscall196(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall196(mut ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall196 (lstat64) {}", _which); - let path = varargs.get_str(ctx); - let real_path_owned = utils::get_cstr_path(ctx, path as *const _); + let path = varargs.get_str(&ctx); + let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), path as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { path }; - let buf_ptr: u32 = varargs.get(ctx); + let buf_ptr: u32 = varargs.get(&ctx); unsafe { let mut stat: stat = std::mem::zeroed(); @@ -1034,7 +1036,7 @@ pub fn ___syscall196(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { } // getuid -pub fn ___syscall199(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall199(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall199 (getuid)"); let uid = unsafe { getuid() as _ }; debug!(" => {}", uid); @@ -1044,20 +1046,20 @@ pub fn ___syscall199(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { // getdents // dirent structure is // i64, i64, u16 (280), i8, [i8; 256] -pub fn ___syscall220(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall220(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { use super::super::env::get_emscripten_data; - let fd: i32 = varargs.get(ctx); - let dirp_addr: i32 = varargs.get(ctx); - let count: u32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let dirp_addr: i32 = varargs.get(&ctx); + let count: u32 = varargs.get(&ctx); debug!( "emscripten::___syscall220 (getdents) {} {} {}", fd, dirp_addr, count ); - let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8; + let dirp = emscripten_memory_pointer!(ctx, ctx.data().memory(0), dirp_addr) as *mut u8; - let opened_dirs = &mut get_emscripten_data(ctx).opened_dirs; + let opened_dirs = &mut get_emscripten_data(&ctx).opened_dirs; // need to persist stream across calls? // let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) }; @@ -1108,11 +1110,11 @@ pub fn ___syscall220(ctx: &EmEnv, _which: i32, mut varargs: VarArgs) -> i32 { } // fcntl64 -pub fn ___syscall221(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall221(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall221 (fcntl64) {}", _which); - let fd: i32 = varargs.get(ctx); - let cmd: i32 = varargs.get(ctx); - let arg: i32 = varargs.get(ctx); + let fd: i32 = varargs.get(&ctx); + let cmd: i32 = varargs.get(&ctx); + let arg: i32 = varargs.get(&ctx); // (FAPPEND - 0x08 // |FASYNC - 0x40 // |FFSYNC - 0x80 @@ -1126,12 +1128,12 @@ pub fn ___syscall221(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int } /// fallocate -pub fn ___syscall324(ctx: &EmEnv, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall324(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall324 (fallocate) {}", _which); - let _fd: c_int = varargs.get(ctx); - let _mode: c_int = varargs.get(ctx); - let _offset: off_t = varargs.get(ctx); - let _len: off_t = varargs.get(ctx); + let _fd: c_int = varargs.get(&ctx); + let _mode: c_int = varargs.get(&ctx); + let _offset: off_t = varargs.get(&ctx); + let _len: off_t = varargs.get(&ctx); #[cfg(not(any(target_os = "freebsd", target_vendor = "apple", target_os = "android")))] unsafe { fallocate(_fd, _mode, _offset, _len) diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index d3efea6d520..aa32da5d01c 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -13,6 +13,8 @@ use std::ffi::CString; #[cfg(target_os = "windows")] use libc::time_t; +use wasmer::{AsContextMut, ContextMut}; + #[cfg(target_os = "windows")] #[allow(non_camel_case_types)] type clockid_t = c_int; @@ -50,7 +52,7 @@ const CLOCK_MONOTONIC_COARSE: clockid_t = 6; /// emscripten: _gettimeofday #[allow(clippy::cast_ptr_alignment)] -pub fn _gettimeofday(ctx: &EmEnv, tp: c_int, tz: c_int) -> c_int { +pub fn _gettimeofday(ctx: ContextMut<'_, EmEnv>, tp: c_int, tz: c_int) -> c_int { debug!("emscripten::_gettimeofday {} {}", tp, tz); #[repr(C)] struct GuestTimeVal { @@ -65,7 +67,8 @@ pub fn _gettimeofday(ctx: &EmEnv, tp: c_int, tz: c_int) -> c_int { unsafe { let now = SystemTime::now(); let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap(); - let timeval_struct_ptr = emscripten_memory_pointer!(ctx.memory(0), tp) as *mut GuestTimeVal; + let timeval_struct_ptr = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), tp) as *mut GuestTimeVal; (*timeval_struct_ptr).tv_sec = since_epoch.as_secs() as _; (*timeval_struct_ptr).tv_usec = since_epoch.subsec_nanos() as _; @@ -73,7 +76,7 @@ pub fn _gettimeofday(ctx: &EmEnv, tp: c_int, tz: c_int) -> c_int { 0 } -pub fn _clock_getres(_ctx: &EmEnv, _clk_id: i32, _tp: i32) -> i32 { +pub fn _clock_getres(mut _ctx: ContextMut<'_, EmEnv>, _clk_id: i32, _tp: i32) -> i32 { debug!("emscripten::_clock_getres"); // clock_getres(clk_id, tp) 0 @@ -81,7 +84,7 @@ pub fn _clock_getres(_ctx: &EmEnv, _clk_id: i32, _tp: i32) -> i32 { /// emscripten: _clock_gettime #[allow(clippy::cast_ptr_alignment)] -pub fn _clock_gettime(ctx: &EmEnv, clk_id: clockid_t, tp: c_int) -> c_int { +pub fn _clock_gettime(ctx: ContextMut<'_, EmEnv>, clk_id: clockid_t, tp: c_int) -> c_int { debug!("emscripten::_clock_gettime {} {}", clk_id, tp); // debug!("Memory {:?}", ctx.memory(0)[..]); #[repr(C)] @@ -106,48 +109,48 @@ pub fn _clock_gettime(ctx: &EmEnv, clk_id: clockid_t, tp: c_int) -> c_int { unsafe { let timespec_struct_ptr = - emscripten_memory_pointer!(ctx.memory(0), tp) as *mut GuestTimeSpec; + emscripten_memory_pointer!(ctx, ctx.data().memory(0), tp) as *mut GuestTimeSpec; (*timespec_struct_ptr).tv_sec = (duration / 1_000_000_000) as _; (*timespec_struct_ptr).tv_nsec = (duration % 1_000_000_000) as _; } 0 } -pub fn _clock_settime(_ctx: &EmEnv, _clk_id: i32, _tp: i32) -> i32 { +pub fn _clock_settime(mut _ctx: ContextMut<'_, EmEnv>, _clk_id: i32, _tp: i32) -> i32 { debug!("emscripten::_clock_settime"); // clock_settime(clk_id, tp) 0 } /// emscripten: ___clock_gettime -pub fn ___clock_gettime(ctx: &EmEnv, clk_id: clockid_t, tp: c_int) -> c_int { +pub fn ___clock_gettime(ctx: ContextMut<'_, EmEnv>, clk_id: clockid_t, tp: c_int) -> c_int { debug!("emscripten::___clock_gettime {} {}", clk_id, tp); _clock_gettime(ctx, clk_id, tp) } /// emscripten: _clock -pub fn _clock(_ctx: &EmEnv) -> c_int { +pub fn _clock(mut _ctx: ContextMut<'_, EmEnv>) -> c_int { debug!("emscripten::_clock"); 0 // TODO: unimplemented } /// emscripten: _difftime -pub fn _difftime(_ctx: &EmEnv, t0: u32, t1: u32) -> f64 { +pub fn _difftime(mut _ctx: ContextMut<'_, EmEnv>, t0: u32, t1: u32) -> f64 { debug!("emscripten::_difftime"); (t0 - t1) as _ } -pub fn _gmtime_r(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn _gmtime_r(mut _ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::_gmtime_r"); -1 } -pub fn _mktime(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _mktime(mut _ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_mktime"); -1 } -pub fn _gmtime(_ctx: &EmEnv, _one: i32) -> i32 { +pub fn _gmtime(mut _ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { debug!("emscripten::_gmtime"); -1 } @@ -168,14 +171,14 @@ struct guest_tm { } /// emscripten: _tvset -pub fn _tvset(_ctx: &EmEnv) { +pub fn _tvset(mut _ctx: ContextMut<'_, EmEnv>) { debug!("emscripten::_tvset UNIMPLEMENTED"); } /// formats time as a C string #[allow(clippy::cast_ptr_alignment)] -unsafe fn fmt_time(ctx: &EmEnv, time: u32) -> *const c_char { - let date = &*(emscripten_memory_pointer!(ctx.memory(0), time) as *mut guest_tm); +unsafe fn fmt_time(ctx: ContextMut<'_, EmEnv>, time: u32) -> *const c_char { + let date = &*(emscripten_memory_pointer!(ctx, ctx.data().memory(0), time) as *mut guest_tm); let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; let months = vec![ @@ -199,21 +202,21 @@ unsafe fn fmt_time(ctx: &EmEnv, time: u32) -> *const c_char { } /// emscripten: _asctime -pub fn _asctime(ctx: &EmEnv, time: u32) -> u32 { +pub fn _asctime(mut ctx: ContextMut<'_, EmEnv>, time: u32) -> u32 { debug!("emscripten::_asctime {}", time); unsafe { - let time_str_ptr = fmt_time(ctx, time); + let time_str_ptr = fmt_time(ctx.as_context_mut(), time); copy_cstr_into_wasm(ctx, time_str_ptr) - // let c_str = emscripten_memory_pointer!(ctx.memory(0), res) as *mut i8; + // let c_str = emscripten_memory_pointer!(ctx, ctx.data().memory(0), res) as *mut i8; // use std::ffi::CStr; // debug!("#### cstr = {:?}", CStr::from_ptr(c_str)); } } /// emscripten: _asctime_r -pub fn _asctime_r(ctx: &EmEnv, time: u32, buf: u32) -> u32 { +pub fn _asctime_r(mut ctx: ContextMut<'_, EmEnv>, time: u32, buf: u32) -> u32 { debug!("emscripten::_asctime_r {}, {}", time, buf); unsafe { @@ -221,10 +224,10 @@ pub fn _asctime_r(ctx: &EmEnv, time: u32, buf: u32) -> u32 { // to write out more than 26 bytes (including the null terminator). // See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html // Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator. - let time_str_ptr = fmt_time(ctx, time); + let time_str_ptr = fmt_time(ctx.as_context_mut(), time); write_to_buf(ctx, time_str_ptr, buf, 26) - // let c_str = emscripten_memory_pointer!(ctx.memory(0), res) as *mut i8; + // let c_str = emscripten_memory_pointer!(ctx, ctx.data().memory(0), res) as *mut i8; // use std::ffi::CStr; // debug!("#### cstr = {:?}", CStr::from_ptr(c_str)); } @@ -232,21 +235,22 @@ pub fn _asctime_r(ctx: &EmEnv, time: u32, buf: u32) -> u32 { /// emscripten: _localtime #[allow(clippy::cast_ptr_alignment)] -pub fn _localtime(ctx: &EmEnv, time_p: u32) -> c_int { +pub fn _localtime(mut ctx: ContextMut<'_, EmEnv>, time_p: u32) -> c_int { debug!("emscripten::_localtime {}", time_p); // NOTE: emscripten seems to want tzset() called in this function // https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r let timespec = unsafe { - let time_p_addr = emscripten_memory_pointer!(ctx.memory(0), time_p) as *mut i64; + let time_p_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_p) as *mut i64; let seconds = *time_p_addr; time::OffsetDateTime::from_unix_timestamp(seconds) }; unsafe { - let tm_struct_offset = env::call_malloc(ctx, mem::size_of::() as _); - let tm_struct_ptr = - emscripten_memory_pointer!(ctx.memory(0), tm_struct_offset) as *mut guest_tm; + let tm_struct_offset = + env::call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let tm_struct_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), tm_struct_offset) + as *mut guest_tm; // debug!( // ">>>>>>> time = {}, {}, {}, {}, {}, {}, {}, {}", // result_tm.tm_sec, result_tm.tm_min, result_tm.tm_hour, result_tm.tm_mday, @@ -269,14 +273,14 @@ pub fn _localtime(ctx: &EmEnv, time_p: u32) -> c_int { } /// emscripten: _localtime_r #[allow(clippy::cast_ptr_alignment)] -pub fn _localtime_r(ctx: &EmEnv, time_p: u32, result: u32) -> c_int { +pub fn _localtime_r(ctx: ContextMut<'_, EmEnv>, time_p: u32, result: u32) -> c_int { debug!("emscripten::_localtime_r {}", time_p); // NOTE: emscripten seems to want tzset() called in this function // https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r unsafe { - let seconds = emscripten_memory_pointer!(ctx.memory(0), time_p) as *const i32; + let seconds = emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_p) as *const i32; let timespec = time::OffsetDateTime::from_unix_timestamp_nanos(*seconds as _); // debug!( @@ -285,7 +289,8 @@ pub fn _localtime_r(ctx: &EmEnv, time_p: u32, result: u32) -> c_int { // result_tm.tm_mon, result_tm.tm_year, result_tm.tm_wday, result_tm.tm_yday, // ); - let result_addr = emscripten_memory_pointer!(ctx.memory(0), result) as *mut guest_tm; + let result_addr = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), result) as *mut guest_tm; (*result_addr).tm_sec = timespec.second() as _; (*result_addr).tm_min = timespec.minute() as _; @@ -305,24 +310,27 @@ pub fn _localtime_r(ctx: &EmEnv, time_p: u32, result: u32) -> c_int { /// emscripten: _time #[allow(clippy::cast_ptr_alignment)] -pub fn _time(ctx: &EmEnv, time_p: u32) -> i32 { +pub fn _time(ctx: ContextMut<'_, EmEnv>, time_p: u32) -> i32 { debug!("emscripten::_time {}", time_p); unsafe { - let time_p_addr = emscripten_memory_pointer!(ctx.memory(0), time_p) as *mut i64; + let time_p_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_p) as *mut i64; libc_time(time_p_addr) as i32 // TODO review i64 } } -pub fn _ctime_r(ctx: &EmEnv, time_p: u32, buf: u32) -> u32 { +pub fn _ctime_r(mut ctx: ContextMut<'_, EmEnv>, time_p: u32, buf: u32) -> u32 { debug!("emscripten::_ctime_r {} {}", time_p, buf); - let (result_offset, _result_slice): (u32, &mut [u8]) = unsafe { allocate_on_stack(ctx, 44) }; - let time = _localtime_r(ctx, time_p, result_offset) as u32; + // var stack = stackSave(); + let (result_offset, _result_slice): (u32, &mut [u8]) = + unsafe { allocate_on_stack(&mut ctx.as_context_mut(), 44) }; + let time = _localtime_r(ctx.as_context_mut(), time_p, result_offset) as u32; _asctime_r(ctx, time, buf) + // stackRestore(stack); } -pub fn _ctime(ctx: &EmEnv, time_p: u32) -> u32 { +pub fn _ctime(ctx: ContextMut<'_, EmEnv>, time_p: u32) -> u32 { debug!("emscripten::_ctime {}", time_p); let tm_current = 2414544; _ctime_r(ctx, time_p, tm_current) @@ -331,11 +339,12 @@ pub fn _ctime(ctx: &EmEnv, time_p: u32) -> u32 { /// emscripten: _timegm #[cfg(not(target_os = "windows"))] #[allow(clippy::cast_ptr_alignment)] -pub fn _timegm(ctx: &EmEnv, time_ptr: u32) -> i32 { +pub fn _timegm(ctx: ContextMut<'_, EmEnv>, time_ptr: u32) -> i32 { debug!("emscripten::_timegm {}", time_ptr); unsafe { - let time_p_addr = emscripten_memory_pointer!(ctx.memory(0), time_ptr) as *mut guest_tm; + let time_p_addr = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), time_ptr) as *mut guest_tm; let x: *mut c_char = CString::new("").expect("CString::new failed").into_raw(); let mut rust_tm = libc_tm { @@ -371,7 +380,7 @@ pub fn _timegm(ctx: &EmEnv, time_ptr: u32) -> i32 { } #[cfg(target_os = "windows")] -pub fn _timegm(_ctx: &EmEnv, _time_ptr: c_int) -> i32 { +pub fn _timegm(mut _ctx: ContextMut<'_, EmEnv>, _time_ptr: c_int) -> i32 { debug!( "emscripten::_timegm - UNIMPLEMENTED IN WINDOWS {}", _time_ptr @@ -380,18 +389,24 @@ pub fn _timegm(_ctx: &EmEnv, _time_ptr: c_int) -> i32 { } /// emscripten: _strftime -pub fn _strftime(ctx: &EmEnv, s_ptr: c_int, maxsize: u32, format_ptr: c_int, tm_ptr: c_int) -> i32 { +pub fn _strftime( + ctx: ContextMut<'_, EmEnv>, + s_ptr: c_int, + maxsize: u32, + format_ptr: c_int, + tm_ptr: c_int, +) -> i32 { debug!( "emscripten::_strftime {} {} {} {}", s_ptr, maxsize, format_ptr, tm_ptr ); #[allow(clippy::cast_ptr_alignment)] - let s = emscripten_memory_pointer!(ctx.memory(0), s_ptr) as *mut c_char; + let s = emscripten_memory_pointer!(ctx, ctx.data().memory(0), s_ptr) as *mut c_char; #[allow(clippy::cast_ptr_alignment)] - let format = emscripten_memory_pointer!(ctx.memory(0), format_ptr) as *const c_char; + let format = emscripten_memory_pointer!(ctx, ctx.data().memory(0), format_ptr) as *const c_char; #[allow(clippy::cast_ptr_alignment)] - let tm = emscripten_memory_pointer!(ctx.memory(0), tm_ptr) as *const guest_tm; + let tm = emscripten_memory_pointer!(ctx, ctx.data().memory(0), tm_ptr) as *const guest_tm; let format_string = unsafe { std::ffi::CStr::from_ptr(format).to_str().unwrap() }; @@ -428,7 +443,7 @@ pub fn _strftime(ctx: &EmEnv, s_ptr: c_int, maxsize: u32, format_ptr: c_int, tm_ /// emscripten: _strftime_l pub fn _strftime_l( - ctx: &EmEnv, + ctx: ContextMut<'_, EmEnv>, s_ptr: c_int, maxsize: u32, format_ptr: c_int, diff --git a/lib/emscripten/src/ucontext.rs b/lib/emscripten/src/ucontext.rs index 7fda8656ea0..d987cb0ba1c 100644 --- a/lib/emscripten/src/ucontext.rs +++ b/lib/emscripten/src/ucontext.rs @@ -1,20 +1,27 @@ use crate::EmEnv; +use wasmer::ContextMut; -pub fn _getcontext(_ctx: &EmEnv, _ucp: i32) -> i32 { +pub fn _getcontext(mut _ctx: ContextMut<'_, EmEnv>, _ucp: i32) -> i32 { debug!("emscripten::_getcontext({})", _ucp); 0 } -pub fn _makecontext(_ctx: &EmEnv, _ucp: i32, _func: i32, _argc: i32, _argv: i32) { +pub fn _makecontext( + mut _ctx: ContextMut<'_, EmEnv>, + _ucp: i32, + _func: i32, + _argc: i32, + _argv: i32, +) { debug!( "emscripten::_makecontext({}, {}, {}, {})", _ucp, _func, _argc, _argv ); } -pub fn _setcontext(_ctx: &EmEnv, _ucp: i32) -> i32 { +pub fn _setcontext(mut _ctx: ContextMut<'_, EmEnv>, _ucp: i32) -> i32 { debug!("emscripten::_setcontext({})", _ucp); 0 } -pub fn _swapcontext(_ctx: &EmEnv, _oucp: i32, _ucp: i32) -> i32 { +pub fn _swapcontext(mut _ctx: ContextMut<'_, EmEnv>, _oucp: i32, _ucp: i32) -> i32 { debug!("emscripten::_swapcontext({}, {})", _oucp, _ucp); 0 } diff --git a/lib/emscripten/src/unistd.rs b/lib/emscripten/src/unistd.rs index ecb08a371f6..7a6090199bd 100644 --- a/lib/emscripten/src/unistd.rs +++ b/lib/emscripten/src/unistd.rs @@ -1,6 +1,7 @@ use crate::EmEnv; +use wasmer::ContextMut; -pub fn confstr(_ctx: &EmEnv, _name: i32, _buf_pointer: i32, _len: i32) -> i32 { +pub fn confstr(mut _ctx: ContextMut<'_, EmEnv>, _name: i32, _buf_pointer: i32, _len: i32) -> i32 { debug!("unistd::confstr({}, {}, {})", _name, _buf_pointer, _len); 0 } diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index b535a1c9f3c..b881f88eea6 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -1,5 +1,5 @@ use super::env; -use super::env::get_emscripten_data; +use super::env::{get_emscripten_data, get_emscripten_funcs}; use crate::storage::align_memory; use crate::EmEnv; use libc::stat; @@ -8,7 +8,7 @@ use std::mem::size_of; use std::os::raw::c_char; use std::path::PathBuf; use std::slice; -use wasmer::{GlobalInit, Memory, Module, Pages, WasmPtr}; +use wasmer::{AsContextMut, ContextMut, GlobalInit, Memory, Module, Pages, WasmPtr}; /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { @@ -93,8 +93,13 @@ pub fn get_emscripten_metadata(module: &Module) -> Result, St } } -pub unsafe fn write_to_buf(ctx: &EmEnv, string: *const c_char, buf: u32, max: u32) -> u32 { - let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_char; +pub unsafe fn write_to_buf( + ctx: ContextMut<'_, EmEnv>, + string: *const c_char, + buf: u32, + max: u32, +) -> u32 { + let buf_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut c_char; for i in 0..max { *buf_addr.add(i as _) = *string.add(i as _); @@ -104,11 +109,12 @@ pub unsafe fn write_to_buf(ctx: &EmEnv, string: *const c_char, buf: u32, max: u3 } /// This function expects nullbyte to be appended. -pub unsafe fn copy_cstr_into_wasm(ctx: &EmEnv, cstr: *const c_char) -> u32 { +pub unsafe fn copy_cstr_into_wasm(mut ctx: ContextMut<'_, EmEnv>, cstr: *const c_char) -> u32 { let s = CStr::from_ptr(cstr).to_str().unwrap(); let cstr_len = s.len(); - let space_offset = env::call_malloc(ctx, (cstr_len as u32) + 1); - let raw_memory = emscripten_memory_pointer!(ctx.memory(0), space_offset) as *mut c_char; + let space_offset = env::call_malloc(ctx.as_context_mut(), (cstr_len as u32) + 1); + let raw_memory = + emscripten_memory_pointer!(ctx, ctx.data().memory(0), space_offset) as *mut c_char; let slice = slice::from_raw_parts_mut(raw_memory, cstr_len); for (byte, loc) in s.bytes().zip(slice.iter_mut()) { @@ -124,14 +130,16 @@ pub unsafe fn copy_cstr_into_wasm(ctx: &EmEnv, cstr: *const c_char) -> u32 { /// # Safety /// This method is unsafe because it operates directly with the slice of memory represented by the address -pub unsafe fn allocate_on_stack(ctx: &EmEnv, count: u32) -> (u32, &mut [T]) { - let offset = get_emscripten_data(ctx) - .stack_alloc_ref() - .unwrap() - .call(count * (size_of::() as u32)) +pub unsafe fn allocate_on_stack<'a, T: Copy>( + ctx: &mut ContextMut<'a, EmEnv>, + count: u32, +) -> (u32, &'a mut [T]) { + let stack_alloc_ref = get_emscripten_funcs(ctx).stack_alloc_ref().unwrap().clone(); + let offset = stack_alloc_ref + .call(&mut ctx.as_context_mut(), count * (size_of::() as u32)) .unwrap(); - let addr = emscripten_memory_pointer!(ctx.memory(0), offset) as *mut T; + let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), offset) as *mut T; let slice = slice::from_raw_parts_mut(addr, count as usize); (offset, slice) @@ -139,7 +147,10 @@ pub unsafe fn allocate_on_stack(ctx: &EmEnv, count: u32) -> (u32, &mut /// # Safety /// This method is unsafe because it uses `allocate_on_stack` which is unsafe -pub unsafe fn allocate_cstr_on_stack<'a>(ctx: &'a EmEnv, s: &str) -> (u32, &'a [u8]) { +pub unsafe fn allocate_cstr_on_stack<'a>( + ctx: &'a mut ContextMut<'a, EmEnv>, + s: &str, +) -> (u32, &'a [u8]) { let (offset, slice) = allocate_on_stack(ctx, (s.len() + 1) as u32); use std::iter; @@ -151,7 +162,10 @@ pub unsafe fn allocate_cstr_on_stack<'a>(ctx: &'a EmEnv, s: &str) -> (u32, &'a [ } #[cfg(not(target_os = "windows"))] -pub unsafe fn copy_terminated_array_of_cstrs(_ctx: &EmEnv, cstrs: *mut *mut c_char) -> u32 { +pub unsafe fn copy_terminated_array_of_cstrs( + mut _ctx: ContextMut<'_, EmEnv>, + cstrs: *mut *mut c_char, +) -> u32 { let _total_num = { let mut ptr = cstrs; let mut counter = 0; @@ -189,8 +203,8 @@ pub struct GuestStat { } #[allow(clippy::cast_ptr_alignment)] -pub unsafe fn copy_stat_into_wasm(ctx: &EmEnv, buf: u32, stat: &stat) { - let stat_ptr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut GuestStat; +pub unsafe fn copy_stat_into_wasm(ctx: ContextMut<'_, EmEnv>, buf: u32, stat: &stat) { + let stat_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut GuestStat; (*stat_ptr).st_dev = stat.st_dev as _; (*stat_ptr).__st_dev_padding = 0; (*stat_ptr).__st_ino_truncated = stat.st_ino as _; @@ -217,20 +231,20 @@ pub unsafe fn copy_stat_into_wasm(ctx: &EmEnv, buf: u32, stat: &stat) { } #[allow(dead_code)] // it's used in `env/windows/mod.rs`. -pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String { +pub fn read_string_from_wasm(ctx: ContextMut<'_, EmEnv>, memory: &Memory, offset: u32) -> String { WasmPtr::::new(offset) - .read_utf8_string_with_nul(memory) + .read_utf8_string_with_nul(&ctx, memory) .unwrap() } /// This function trys to find an entry in mapdir /// translating paths into their correct value -pub fn get_cstr_path(ctx: &EmEnv, path: *const i8) -> Option { +pub fn get_cstr_path(ctx: ContextMut<'_, EmEnv>, path: *const i8) -> Option { use std::collections::VecDeque; let path_str = unsafe { std::ffi::CStr::from_ptr(path as *const _).to_str().unwrap() }.to_string(); - let data = get_emscripten_data(ctx); + let data = get_emscripten_data(&ctx); let path = PathBuf::from(path_str); let mut prefix_added = false; let mut components = path.components().collect::>(); @@ -261,13 +275,13 @@ pub fn get_cstr_path(ctx: &EmEnv, path: *const i8) -> Option /// gets the current directory /// handles mapdir logic -pub fn get_current_directory(ctx: &EmEnv) -> Option { - if let Some(val) = get_emscripten_data(ctx).mapped_dirs.get(".") { +pub fn get_current_directory(ctx: ContextMut<'_, EmEnv>) -> Option { + if let Some(val) = get_emscripten_data(&ctx).mapped_dirs.get(".") { return Some(val.clone()); } std::env::current_dir() .map(|cwd| { - if let Some(val) = get_emscripten_data(ctx) + if let Some(val) = get_emscripten_data(&ctx) .mapped_dirs .get(&cwd.to_string_lossy().to_string()) { diff --git a/lib/emscripten/src/varargs.rs b/lib/emscripten/src/varargs.rs index e287d3b6767..826dc15cf9b 100644 --- a/lib/emscripten/src/varargs.rs +++ b/lib/emscripten/src/varargs.rs @@ -3,6 +3,7 @@ use std::mem; use wasmer::FromToNativeWasmType; // use std::ffi::CStr; use std::os::raw::c_char; +use wasmer::ContextMut; #[repr(transparent)] #[derive(Copy, Clone)] @@ -11,15 +12,18 @@ pub struct VarArgs { } impl VarArgs { - pub fn get(&mut self, ctx: &EmEnv) -> T { - let ptr = emscripten_memory_pointer!(ctx.memory(0), self.pointer); + pub fn get(&mut self, ctx: &ContextMut<'_, EmEnv>) -> T { + let ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), self.pointer); self.pointer += mem::size_of::() as u32; unsafe { (ptr as *const T).read() } } - pub fn get_str(&mut self, ctx: &EmEnv) -> *const c_char { + // pub fn getStr<'a>(&mut self, ctx: &mut Ctx) -> &'a CStr { + pub fn get_str(&mut self, ctx: &ContextMut<'_, EmEnv>) -> *const c_char { let ptr_addr: u32 = self.get(ctx); - emscripten_memory_pointer!(ctx.memory(0), ptr_addr) as *const c_char + let ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), ptr_addr) as *const c_char; + ptr + // unsafe { CStr::from_ptr(ptr) } } } From bc58b713dbc1ea6e6c6054edf7efe6965ae81d41 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Wed, 1 Jun 2022 15:43:07 +0200 Subject: [PATCH 08/24] Migrate wasmer-cli to new Context API --- lib/cli/src/commands/run.rs | 130 ++++++++++++++---------- lib/cli/src/commands/run/wasi.rs | 23 +++-- lib/cli/src/commands/wast.rs | 4 +- lib/emscripten/src/emscripten_target.rs | 4 +- lib/emscripten/src/env/mod.rs | 2 +- lib/emscripten/src/lib.rs | 26 +++-- lib/emscripten/src/memory.rs | 6 +- lib/emscripten/src/syscalls/unix.rs | 3 +- lib/emscripten/src/utils.rs | 11 +- 9 files changed, 133 insertions(+), 76 deletions(-) diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index ea5e38f415d..b5ee6e6f0b4 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -7,9 +7,11 @@ use crate::warning; use anyhow::{anyhow, Context, Result}; use std::path::PathBuf; use std::str::FromStr; +use wasmer::Context as WasmerContext; use wasmer::*; #[cfg(feature = "cache")] use wasmer_cache::{Cache, FileSystemCache, Hash}; +use wasmer_types::Type as ValueType; use structopt::StructOpt; @@ -95,6 +97,41 @@ impl Run { }) } + fn inner_run(&self, mut ctx: WasmerContext, instance: Instance) -> Result<()> { + let module = self.get_module()?; + // If this module exports an _initialize function, run that first. + if let Ok(initialize) = instance.exports.get_function("_initialize") { + initialize + .call(&mut ctx, &[]) + .with_context(|| "failed to run _initialize function")?; + } + + // Do we want to invoke a function? + if let Some(ref invoke) = self.invoke { + let imports = imports! {}; + let instance = Instance::new(&mut ctx, &module, &imports)?; + let result = + self.invoke_function(&mut ctx.as_context_mut(), &instance, &invoke, &self.args)?; + println!( + "{}", + result + .iter() + .map(|val| val.to_string()) + .collect::>() + .join(" ") + ); + } else { + let start: Function = self.try_find_function(&instance, "_start", &[])?; + let result = start.call(&mut ctx, &[]); + #[cfg(feature = "wasi")] + self.wasi.handle_result(result)?; + #[cfg(not(feature = "wasi"))] + result?; + } + + Ok(()) + } + fn inner_execute(&self) -> Result<()> { let module = self.get_module()?; #[cfg(feature = "emscripten")] @@ -105,12 +142,19 @@ impl Run { }; // TODO: refactor this if is_emscripten_module(&module) { - let mut emscripten_globals = EmscriptenGlobals::new(module.store(), &module) + // create an EmEnv with default global + let mut ctx = WasmerContext::new(module.store(), EmEnv::new()); + let mut emscripten_globals = EmscriptenGlobals::new(ctx.as_context_mut(), &module) .map_err(|e| anyhow!("{}", e))?; - let mut em_env = EmEnv::new(&emscripten_globals.data, Default::default()); + ctx.data_mut() + .set_data(&emscripten_globals.data, Default::default()); let import_object = - generate_emscripten_env(module.store(), &mut emscripten_globals, &em_env); - let mut instance = match Instance::new(&module, &import_object) { + generate_emscripten_env(&mut ctx.as_context_mut(), &mut emscripten_globals); + let mut instance = match Instance::new( + &mut ctx.as_context_mut(), + &module, + &import_object, + ) { Ok(instance) => instance, Err(e) => { let err: Result<(), _> = Err(e); @@ -126,7 +170,7 @@ impl Run { run_emscripten_instance( &mut instance, - &mut em_env, + ctx.as_context_mut(), &mut emscripten_globals, if let Some(cn) = &self.command_name { cn @@ -142,7 +186,7 @@ impl Run { // If WASI is enabled, try to execute it with it #[cfg(feature = "wasi")] - let instance = { + let ret = { use std::collections::BTreeSet; use wasmer_wasi::WasiVersion; @@ -175,47 +219,28 @@ impl Run { .map(|f| f.to_string_lossy().to_string()) }) .unwrap_or_default(); - self.wasi + let (ctx, instance) = self + .wasi .instantiate(&module, program_name, self.args.clone()) - .with_context(|| "failed to instantiate WASI module")? + .with_context(|| "failed to instantiate WASI module")?; + self.inner_run(ctx, instance) } // not WASI - _ => Instance::new(&module, &imports! {})?, + _ => { + let mut ctx = WasmerContext::new(module.store(), ()); + let instance = Instance::new(&mut ctx, &module, &imports! {})?; + self.inner_run(ctx, instance) + } } }; #[cfg(not(feature = "wasi"))] - let instance = Instance::new(&module, &imports! {})?; - - // If this module exports an _initialize function, run that first. - if let Ok(initialize) = instance.exports.get_function("_initialize") { - initialize - .call(&[]) - .with_context(|| "failed to run _initialize function")?; - } - - // Do we want to invoke a function? - if let Some(ref invoke) = self.invoke { - let imports = imports! {}; - let instance = Instance::new(&module, &imports)?; - let result = self.invoke_function(&instance, invoke, &self.args)?; - println!( - "{}", - result - .iter() - .map(|val| val.to_string()) - .collect::>() - .join(" ") - ); - } else { - let start: Function = self.try_find_function(&instance, "_start", &[])?; - let result = start.call(&[]); - #[cfg(feature = "wasi")] - self.wasi.handle_result(result)?; - #[cfg(not(feature = "wasi"))] - result?; - } + let ret = { + let mut ctx = WasmerContext::new(module.store(), ()); + let instance = Instance::new(&mut ctx, &module, &imports! {})?; + self.inner_run(ctx, instance) + }; - Ok(()) + ret } fn get_module(&self) -> Result { @@ -350,12 +375,13 @@ impl Run { fn invoke_function( &self, + ctx: &mut impl AsContextMut, instance: &Instance, invoke: &str, args: &[String], - ) -> Result> { - let func: Function = self.try_find_function(instance, invoke, args)?; - let func_ty = func.ty(); + ) -> Result> { + let func: Function = self.try_find_function(&instance, invoke, args)?; + let func_ty = func.ty(ctx); let required_arguments = func_ty.params().len(); let provided_arguments = args.len(); if required_arguments != provided_arguments { @@ -370,23 +396,23 @@ impl Run { .iter() .zip(func_ty.params().iter()) .map(|(arg, param_type)| match param_type { - ValType::I32 => { - Ok(Val::I32(arg.parse().map_err(|_| { + ValueType::I32 => { + Ok(Value::I32(arg.parse().map_err(|_| { anyhow!("Can't convert `{}` into a i32", arg) })?)) } - ValType::I64 => { - Ok(Val::I64(arg.parse().map_err(|_| { + ValueType::I64 => { + Ok(Value::I64(arg.parse().map_err(|_| { anyhow!("Can't convert `{}` into a i64", arg) })?)) } - ValType::F32 => { - Ok(Val::F32(arg.parse().map_err(|_| { + ValueType::F32 => { + Ok(Value::F32(arg.parse().map_err(|_| { anyhow!("Can't convert `{}` into a f32", arg) })?)) } - ValType::F64 => { - Ok(Val::F64(arg.parse().map_err(|_| { + ValueType::F64 => { + Ok(Value::F64(arg.parse().map_err(|_| { anyhow!("Can't convert `{}` into a f64", arg) })?)) } @@ -397,7 +423,7 @@ impl Run { )), }) .collect::>>()?; - Ok(func.call(&invoke_args)?) + Ok(func.call(ctx, &invoke_args)?) } /// Create Run instance for arguments/env, diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index f7e19820791..60be4660e33 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -2,8 +2,11 @@ use crate::utils::{parse_envvar, parse_mapdir}; use anyhow::Result; use std::collections::BTreeSet; use std::path::PathBuf; -use wasmer::{Instance, Module, RuntimeError, Val}; -use wasmer_wasi::{get_wasi_versions, is_wasix_module, WasiError, WasiState, WasiVersion}; +use wasmer::{AsContextMut, Context, Instance, Module, RuntimeError, Value}; +use wasmer_wasi::{ + get_wasi_versions, import_object_for_all_wasi_versions, is_wasix_module, WasiEnv, WasiError, + WasiState, WasiVersion, +}; use structopt::StructOpt; @@ -78,7 +81,7 @@ impl Wasi { module: &Module, program_name: String, args: Vec, - ) -> Result { + ) -> Result<(Context, Instance)> { let args = args.iter().cloned().map(|arg| arg.into_bytes()); let mut wasi_state_builder = WasiState::new(program_name); @@ -96,19 +99,21 @@ impl Wasi { } } - let mut wasi_env = wasi_state_builder.finalize()?; + let wasi_env = wasi_state_builder.finalize()?; wasi_env.state.fs.is_wasix.store( is_wasix_module(module), std::sync::atomic::Ordering::Release, ); - - let import_object = wasi_env.import_object_for_all_wasi_versions(module)?; - let instance = Instance::new(module, &import_object)?; - Ok(instance) + let mut ctx = Context::new(module.store(), wasi_env.clone()); + let import_object = import_object_for_all_wasi_versions(&mut ctx.as_context_mut()); + let instance = Instance::new(&mut ctx, &module, &import_object)?; + let memory = instance.exports.get_memory("memory")?; + ctx.data_mut().set_memory(memory.clone()); + Ok((ctx, instance)) } /// Helper function for handling the result of a Wasi _start function. - pub fn handle_result(&self, result: Result, RuntimeError>) -> Result<()> { + pub fn handle_result(&self, result: Result, RuntimeError>) -> Result<()> { match result { Ok(_) => Ok(()), Err(err) => { diff --git a/lib/cli/src/commands/wast.rs b/lib/cli/src/commands/wast.rs index 580bdb205e1..5dd0352c4d1 100644 --- a/lib/cli/src/commands/wast.rs +++ b/lib/cli/src/commands/wast.rs @@ -3,6 +3,7 @@ use crate::store::StoreOptions; use anyhow::{Context, Result}; use std::path::PathBuf; use structopt::StructOpt; +use wasmer::Context as WasmerContext; use wasmer_wast::Wast as WastSpectest; #[derive(Debug, StructOpt)] @@ -28,7 +29,8 @@ impl Wast { } fn inner_execute(&self) -> Result<()> { let (store, _compiler_name) = self.store.get_store()?; - let mut wast = WastSpectest::new_with_spectest(store); + let ctx = WasmerContext::new(&store, ()); + let mut wast = WastSpectest::new_with_spectest(ctx); wast.fail_fast = self.fail_fast; wast.run_file(&self.path).with_context(|| "tests failed")?; eprintln!("Wast tests succeeded for `{}`.", self.path.display()); diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs index e299e862b7c..4bf614c40f1 100644 --- a/lib/emscripten/src/emscripten_target.rs +++ b/lib/emscripten/src/emscripten_target.rs @@ -17,12 +17,12 @@ pub fn exit_with_live_runtime(_ctx: ContextMut<'_, EmEnv>) { pub fn setTempRet0(ctx: ContextMut<'_, EmEnv>, val: i32) { trace!("emscripten::setTempRet0: {}", val); - get_emscripten_data(&ctx).temp_ret_0 = val; + get_emscripten_data(&ctx).as_mut().unwrap().temp_ret_0 = val; } pub fn getTempRet0(ctx: ContextMut<'_, EmEnv>) -> i32 { trace!("emscripten::getTempRet0"); - get_emscripten_data(&ctx).temp_ret_0 + get_emscripten_data(&ctx).as_ref().unwrap().temp_ret_0 } pub fn _alarm(_ctx: ContextMut<'_, EmEnv>, _seconds: u32) -> i32 { diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 5985293941b..fa7c1ab1edc 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -45,7 +45,7 @@ pub fn call_memset(mut ctx: ContextMut<'_, EmEnv>, pointer: u32, value: u32, siz pub(crate) fn get_emscripten_data<'a>( ctx: &'a ContextMut<'_, EmEnv>, -) -> MutexGuard<'a, EmscriptenData> { +) -> MutexGuard<'a, Option> { ctx.data().data.lock().unwrap() } diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 45befa144f9..243600ad95b 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -78,15 +78,22 @@ pub use self::utils::{ /// The environment provided to the Emscripten imports. pub struct EmEnv { memory: Arc>>, - data: Arc>, + data: Arc>>, funcs: Arc>, } +impl Default for EmEnv { + fn default() -> Self { + Self::new() + } +} + impl EmEnv { - pub fn new(data: &EmscriptenGlobalsData, mapped_dirs: HashMap) -> Self { + /// Create a new EmEnv, with default value to be set later (set_memory, set_functions and set_data) + pub fn new() -> Self { Self { memory: Arc::new(RwLock::new(None)), - data: Arc::new(Mutex::new(EmscriptenData::new(data.clone(), mapped_dirs))), + data: Arc::new(Mutex::new(None)), funcs: Arc::new(Mutex::new(EmscriptenFunctions::new())), } } @@ -105,11 +112,14 @@ impl EmEnv { self.funcs = Arc::new(Mutex::new(funcs)); } - // pub fn init_with_instance(&mut self, instance: &Instance) -> Result<(), wasmer::HostEnvInitError> { - // let mut ed = self.data.lock().unwrap(); - // ed.init_with_instance(instance)?; - // Ok(()) - // } + pub fn set_data( + &mut self, + data: &EmscriptenGlobalsData, + mapped_dirs: HashMap, + ) { + let mut w = self.data.lock().unwrap(); + *w = Some(EmscriptenData::new(data.clone(), mapped_dirs)); + } } #[derive(Debug, Clone)] diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index eccf2d8b5c7..065aaaec429 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -88,7 +88,11 @@ pub fn sbrk(mut ctx: ContextMut<'_, EmEnv>, increment: i32) -> i32 { // let old_dynamic_top = 0; // let new_dynamic_top = 0; let memory = ctx.data().memory(0); - let top_ptr = get_emscripten_data(&ctx).globals.dynamictop_ptr; + let top_ptr = get_emscripten_data(&ctx) + .as_ref() + .unwrap() + .globals + .dynamictop_ptr; let dynamictop_ptr = WasmPtr::::new(top_ptr).deref(&ctx, &memory); let old_dynamic_top = dynamictop_ptr.read().unwrap(); let new_dynamic_top: i32 = old_dynamic_top + increment; diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 109fb25d6c0..ea402a33a63 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -1059,7 +1059,8 @@ pub fn ___syscall220(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarAr let dirp = emscripten_memory_pointer!(ctx, ctx.data().memory(0), dirp_addr) as *mut u8; - let opened_dirs = &mut get_emscripten_data(&ctx).opened_dirs; + let data = &mut get_emscripten_data(&ctx); + let opened_dirs = &mut data.as_mut().unwrap().opened_dirs; // need to persist stream across calls? // let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) }; diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index b881f88eea6..303c277fa87 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -258,6 +258,8 @@ pub fn get_cstr_path(ctx: ContextMut<'_, EmEnv>, path: *const i8) -> Option, path: *const i8) -> Option) -> Option { - if let Some(val) = get_emscripten_data(&ctx).mapped_dirs.get(".") { + if let Some(val) = get_emscripten_data(&ctx) + .as_ref() + .unwrap() + .mapped_dirs + .get(".") + { return Some(val.clone()); } std::env::current_dir() .map(|cwd| { if let Some(val) = get_emscripten_data(&ctx) + .as_ref() + .unwrap() .mapped_dirs .get(&cwd.to_string_lossy().to_string()) { From 84225773ee6fb28b23768b866357765315cf559d Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Fri, 17 Jun 2022 19:45:50 +0200 Subject: [PATCH 09/24] Migrated Emscripten/Windows to new Context API --- lib/emscripten/src/env/windows/mod.rs | 52 ++++++++------- lib/emscripten/src/io/windows.rs | 9 +-- lib/emscripten/src/syscalls/windows.rs | 91 +++++++++++++------------- 3 files changed, 78 insertions(+), 74 deletions(-) diff --git a/lib/emscripten/src/env/windows/mod.rs b/lib/emscripten/src/env/windows/mod.rs index 6a587e1e0d1..dce90272874 100644 --- a/lib/emscripten/src/env/windows/mod.rs +++ b/lib/emscripten/src/env/windows/mod.rs @@ -8,7 +8,7 @@ use std::os::raw::c_char; use crate::env::{call_malloc, EmAddrInfo}; use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm}; use crate::EmEnv; -use wasmer::WasmPtr; +use wasmer::{AsContextMut, ContextMut, WasmPtr}; extern "C" { #[link_name = "_putenv"] @@ -17,10 +17,10 @@ extern "C" { // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; -pub fn _getenv(ctx: &EmEnv, name: u32) -> u32 { +pub fn _getenv(mut ctx: ContextMut<'_, EmEnv>, name: u32) -> u32 { debug!("emscripten::_getenv"); - let memory = ctx.memory(0); - let name_string = read_string_from_wasm(&memory, name); + let memory = ctx.data().memory(0); + let name_string = read_string_from_wasm(ctx.as_context_mut(), &memory, name); debug!("=> name({:?})", name_string); let c_str = unsafe { getenv(name_string.as_ptr() as *const libc::c_char) }; if c_str.is_null() { @@ -30,12 +30,12 @@ pub fn _getenv(ctx: &EmEnv, name: u32) -> u32 { } /// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int); -pub fn _setenv(ctx: &EmEnv, name: u32, value: u32, _overwrite: u32) -> c_int { +pub fn _setenv(mut ctx: ContextMut<'_, EmEnv>, name: u32, value: u32, _overwrite: u32) -> c_int { debug!("emscripten::_setenv"); - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); // setenv does not exist on windows, so we hack it with _putenv - let name = read_string_from_wasm(&memory, name); - let value = read_string_from_wasm(&memory, value); + let name = read_string_from_wasm(ctx.as_context_mut(), &memory, name); + let value = read_string_from_wasm(ctx, &memory, value); let putenv_string = format!("{}={}", name, value); let putenv_cstring = CString::new(putenv_string).unwrap(); let putenv_raw_ptr = putenv_cstring.as_ptr(); @@ -45,10 +45,10 @@ pub fn _setenv(ctx: &EmEnv, name: u32, value: u32, _overwrite: u32) -> c_int { } /// emscripten: _putenv // (name: *const char); -pub fn _putenv(ctx: &EmEnv, name: c_int) -> c_int { +pub fn _putenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { debug!("emscripten::_putenv"); - let memory = ctx.memory(0); - let name_addr = emscripten_memory_pointer!(&memory, name) as *const c_char; + let memory = ctx.data().memory(0); + let name_addr = emscripten_memory_pointer!(ctx, &memory, name) as *const c_char; debug!("=> name({:?})", unsafe { std::ffi::CStr::from_ptr(name_addr) }); @@ -56,10 +56,10 @@ pub fn _putenv(ctx: &EmEnv, name: c_int) -> c_int { } /// emscripten: _unsetenv // (name: *const char); -pub fn _unsetenv(ctx: &EmEnv, name: u32) -> c_int { +pub fn _unsetenv(ctx: ContextMut<'_, EmEnv>, name: u32) -> c_int { debug!("emscripten::_unsetenv"); - let memory = ctx.memory(0); - let name = read_string_from_wasm(&memory, name); + let memory = ctx.data().memory(0); + let name = read_string_from_wasm(ctx, &memory, name); // no unsetenv on windows, so use putenv with an empty value let unsetenv_string = format!("{}=", name); let unsetenv_cstring = CString::new(unsetenv_string).unwrap(); @@ -69,11 +69,11 @@ pub fn _unsetenv(ctx: &EmEnv, name: u32) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getpwnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { +pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { debug!("emscripten::_getpwnam {}", name_ptr); #[cfg(not(feature = "debug"))] let _ = name_ptr; - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); #[repr(C)] struct GuestPasswd { @@ -88,9 +88,10 @@ pub fn _getpwnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { // stub this in windows as it is not valid unsafe { - let passwd_struct_offset = call_malloc(ctx, mem::size_of::() as _); + let passwd_struct_offset = + call_malloc(ctx.as_context_mut(), mem::size_of::() as _); let passwd_struct_ptr = - emscripten_memory_pointer!(&memory, passwd_struct_offset) as *mut GuestPasswd; + emscripten_memory_pointer!(ctx, memory, passwd_struct_offset) as *mut GuestPasswd; (*passwd_struct_ptr).pw_name = 0; (*passwd_struct_ptr).pw_passwd = 0; (*passwd_struct_ptr).pw_gecos = 0; @@ -104,11 +105,11 @@ pub fn _getpwnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { +pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { debug!("emscripten::_getgrnam {}", name_ptr); #[cfg(not(feature = "debug"))] let _ = name_ptr; - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); #[repr(C)] struct GuestGroup { @@ -120,9 +121,10 @@ pub fn _getgrnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { // stub the group struct as it is not supported on windows unsafe { - let group_struct_offset = call_malloc(ctx, mem::size_of::() as _); + let group_struct_offset = + call_malloc(ctx.as_context_mut(), mem::size_of::() as _); let group_struct_ptr = - emscripten_memory_pointer!(&memory, group_struct_offset) as *mut GuestGroup; + emscripten_memory_pointer!(ctx, memory, group_struct_offset) as *mut GuestGroup; (*group_struct_ptr).gr_name = 0; (*group_struct_ptr).gr_passwd = 0; (*group_struct_ptr).gr_gid = 0; @@ -131,7 +133,7 @@ pub fn _getgrnam(ctx: &EmEnv, name_ptr: c_int) -> c_int { } } -pub fn _sysconf(_ctx: &EmEnv, name: c_int) -> c_long { +pub fn _sysconf(_ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_long { debug!("emscripten::_sysconf {}", name); #[cfg(not(feature = "debug"))] let _ = name; @@ -139,13 +141,13 @@ pub fn _sysconf(_ctx: &EmEnv, name: c_int) -> c_long { 0 } -pub fn _gai_strerror(_ctx: &EmEnv, _ecode: i32) -> i32 { +pub fn _gai_strerror(_ctx: ContextMut<'_, EmEnv>, _ecode: i32) -> i32 { debug!("emscripten::_gai_strerror({}) - stub", _ecode); -1 } pub fn _getaddrinfo( - _ctx: &EmEnv, + _ctx: ContextMut<'_, EmEnv>, _node_ptr: WasmPtr, _service_str_ptr: WasmPtr, _hints_ptr: WasmPtr, diff --git a/lib/emscripten/src/io/windows.rs b/lib/emscripten/src/io/windows.rs index e0507ead876..0bd1d8fbc31 100644 --- a/lib/emscripten/src/io/windows.rs +++ b/lib/emscripten/src/io/windows.rs @@ -1,4 +1,5 @@ use crate::EmEnv; +use wasmer::ContextMut; // This may be problematic for msvc which uses inline functions for the printf family // this cfg_attr will try to link with the legacy lib that does not inline printf @@ -14,12 +15,12 @@ use crate::EmEnv; //} /// putchar -pub fn putchar(_ctx: &EmEnv, chr: i32) { +pub fn putchar(_ctx: ContextMut<'_, EmEnv>, chr: i32) { unsafe { libc::putchar(chr) }; } /// printf -pub fn printf(_ctx: &EmEnv, memory_offset: i32, extra: i32) -> i32 { +pub fn printf(_ctx: ContextMut<'_, EmEnv>, memory_offset: i32, extra: i32) -> i32 { debug!("emscripten::printf {}, {}", memory_offset, extra); #[cfg(not(feature = "debug"))] { @@ -34,13 +35,13 @@ pub fn printf(_ctx: &EmEnv, memory_offset: i32, extra: i32) -> i32 { } /// chroot -pub fn chroot(_ctx: &EmEnv, _name_ptr: i32) -> i32 { +pub fn chroot(_ctx: ContextMut<'_, EmEnv>, _name_ptr: i32) -> i32 { debug!("emscripten::chroot"); unimplemented!("emscripten::chroot") } /// getpwuid -pub fn getpwuid(_ctx: &EmEnv, _uid: i32) -> i32 { +pub fn getpwuid(_ctx: ContextMut<'_, EmEnv>, _uid: i32) -> i32 { debug!("emscripten::getpwuid"); unimplemented!("emscripten::getpwuid") } diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index 169b5f836f6..3c16821c940 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -8,26 +8,27 @@ use std::ffi::CString; use std::fs::File; use std::io::Write; use std::os::raw::c_int; +use wasmer::{AsContextMut, ContextMut}; #[allow(non_camel_case_types)] type pid_t = c_int; /// open -pub fn ___syscall5(ctx: &EmEnv, which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall5(mut ctx: ContextMut<'_, EmEnv>, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall5 (open) {}", which); #[cfg(not(feature = "debug"))] let _ = which; - let pathname_addr = varargs.get_str(ctx); - let real_path_owned = get_cstr_path(ctx, pathname_addr); + let pathname_addr = varargs.get_str(&ctx); + let real_path_owned = get_cstr_path(ctx.as_context_mut(), pathname_addr); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { pathname_addr }; - let flags: i32 = varargs.get(ctx); - let mode: u32 = varargs.get(ctx); + let flags: i32 = varargs.get(&ctx); + let mode: u32 = varargs.get(&ctx); let path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() }; - let memory = ctx.memory(0); + let memory = ctx.data().memory(0); match path_str { "/dev/urandom" => { @@ -44,9 +45,9 @@ pub fn ___syscall5(ctx: &EmEnv, which: c_int, mut varargs: VarArgs) -> c_int { getrandom::getrandom(&mut random_bytes).unwrap(); let _ = urandom_file.write_all(&random_bytes).unwrap(); // put the file path string into wasm memory - let urandom_file_offset = unsafe { copy_cstr_into_wasm(ctx, ptr) }; + let urandom_file_offset = unsafe { copy_cstr_into_wasm(ctx.as_context_mut(), ptr) }; let raw_pointer_to_urandom_file = - emscripten_memory_pointer!(&memory, urandom_file_offset) as *const i8; + emscripten_memory_pointer!(ctx, memory, urandom_file_offset) as *const i8; let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) }; debug!( "=> pathname: {}, flags: {}, mode: {} = fd: {}", @@ -66,19 +67,19 @@ pub fn ___syscall5(ctx: &EmEnv, which: c_int, mut varargs: VarArgs) -> c_int { } /// link -pub fn ___syscall9(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall9(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall9 (link) {}", _which); unimplemented!("emscripten::___syscall9 (link) {}", _which); } /// ftruncate64 -pub fn ___syscall194(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall194(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall194 - stub"); unimplemented!("emscripten::___syscall194 - stub") } // chown -pub fn ___syscall212(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall212(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -86,23 +87,23 @@ pub fn ___syscall212(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int } /// access -pub fn ___syscall33(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall33(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall33 (access) {}", _which); unimplemented!("emscripten::___syscall33 (access) {}", _which); } /// nice -pub fn ___syscall34(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall34(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall34 (nice) {}", _which); unimplemented!("emscripten::___syscall34 (nice) {}", _which); } // mkdir -pub fn ___syscall39(ctx: &EmEnv, which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall39(ctx: ContextMut<'_, EmEnv>, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", which); #[cfg(not(feature = "debug"))] let _ = which; - let pathname_addr = varargs.get_str(ctx); + let pathname_addr = varargs.get_str(&ctx); let real_path_owned = get_cstr_path(ctx, pathname_addr); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() @@ -113,80 +114,80 @@ pub fn ___syscall39(ctx: &EmEnv, which: c_int, mut varargs: VarArgs) -> c_int { } /// dup -pub fn ___syscall41(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall41(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall41 (dup) {}", _which); unimplemented!("emscripten::___syscall41 (dup) {}", _which); } /// getrusage -pub fn ___syscall77(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall77(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall77 (getrusage) {}", _which); unimplemented!("emscripten::___syscall77 (getrusage) {}", _which); } /// symlink -pub fn ___syscall83(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall83(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall83 (symlink) {}", _which); unimplemented!("emscripten::___syscall83 (symlink) {}", _which); } /// readlink -pub fn ___syscall85(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall85(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall85 (readlink) {}", _which); -1 } /// getpgid -pub fn ___syscall132(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall132(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall132 (getpgid)"); -1 } /// lchown -pub fn ___syscall198(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall198(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall198 (lchown) {}", _which); unimplemented!("emscripten::___syscall198 (lchown) {}", _which); } /// getgid32 -pub fn ___syscall200(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall200(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall200 (getgid32)"); unimplemented!("emscripten::___syscall200 (getgid32)"); } // geteuid32 -pub fn ___syscall201(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall201(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (geteuid32)"); unimplemented!("emscripten::___syscall201 (geteuid32)"); } // getegid32 -pub fn ___syscall202(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall202(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { // gid_t debug!("emscripten::___syscall202 (getegid32)"); unimplemented!("emscripten::___syscall202 (getegid32)"); } /// getgroups -pub fn ___syscall205(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall205(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall205 (getgroups) {}", _which); unimplemented!("emscripten::___syscall205 (getgroups) {}", _which); } /// madvise -pub fn ___syscall219(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall219(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); unimplemented!("emscripten::___syscall212 (chown) {}", _which); } /// dup3 -pub fn ___syscall330(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> pid_t { +pub fn ___syscall330(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall330 (dup3)"); -1 } /// ioctl -pub fn ___syscall54(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall54(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall54 (ioctl) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -194,14 +195,14 @@ pub fn ___syscall54(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int } /// fchmod -pub fn ___syscall94(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall94(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fchmod) {}", _which); unimplemented!("emscripten::___syscall118 (fchmod) {}", _which); } // socketcall #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall102(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall102(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall102 (socketcall) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -209,13 +210,13 @@ pub fn ___syscall102(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int } /// fsync -pub fn ___syscall118(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall118(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fsync) {}", _which); unimplemented!("emscripten::___syscall118 (fsync) {}", _which); } // pread -pub fn ___syscall180(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall180(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -223,7 +224,7 @@ pub fn ___syscall180(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int } // pwrite -pub fn ___syscall181(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall181(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall181 (pwrite) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -232,14 +233,14 @@ pub fn ___syscall181(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int /// wait4 #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall114(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> pid_t { +pub fn ___syscall114(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall114 (wait4)"); -1 } // select #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall142(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall142(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall142 (newselect) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -247,13 +248,13 @@ pub fn ___syscall142(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int } /// fdatasync -pub fn ___syscall148(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall148(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall148 (fdatasync) {}", _which); unimplemented!("emscripten::___syscall148 (fdatasync) {}", _which); } // setpgid -pub fn ___syscall57(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall57(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall57 (setpgid) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -262,7 +263,7 @@ pub fn ___syscall57(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall122(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall122 (uname) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -270,43 +271,43 @@ pub fn ___syscall122(_ctx: &EmEnv, which: c_int, mut _varargs: VarArgs) -> c_int } /// poll -pub fn ___syscall168(_ctx: &EmEnv, _which: i32, _varargs: VarArgs) -> i32 { +pub fn ___syscall168(_ctx: ContextMut<'_, EmEnv>, _which: i32, _varargs: VarArgs) -> i32 { debug!("emscripten::___syscall168(poll) - stub"); -1 } /// lstat64 -pub fn ___syscall196(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall196(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall196 (lstat64) - stub"); -1 } // getuid -pub fn ___syscall199(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall199(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall199 (getuid)"); -1 } // getdents -pub fn ___syscall220(_ctx: &EmEnv, _one: i32, _two: i32) -> i32 { +pub fn ___syscall220(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall220"); -1 } // fcntl64 -pub fn ___syscall221(_ctx: &EmEnv, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall221(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall221 (fcntl64) {}", _which); -1 } /// fchown -pub fn ___syscall207(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall207(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall207 (fchown) {}", _which); unimplemented!("emscripten::___syscall207 (fchown) {}", _which) } /// fallocate -pub fn ___syscall324(_ctx: &EmEnv, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall324(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall324 (fallocate) {}", _which); unimplemented!("emscripten::___syscall324 (fallocate) {}", _which) } From decd32fad3852e63928544b4325874641217506e Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 18 Jun 2022 16:47:46 +0300 Subject: [PATCH 10/24] Ported wasmer-middlewares to new Context API --- lib/middlewares/src/metering.rs | 86 ++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/lib/middlewares/src/metering.rs b/lib/middlewares/src/metering.rs index ba9cff4576b..a90faca2388 100644 --- a/lib/middlewares/src/metering.rs +++ b/lib/middlewares/src/metering.rs @@ -13,8 +13,8 @@ use std::fmt; use std::sync::{Arc, Mutex}; use wasmer::wasmparser::{Operator, Type as WpType, TypeOrFuncType as WpTypeOrFuncType}; use wasmer::{ - ExportIndex, FunctionMiddleware, GlobalInit, GlobalType, Instance, LocalFunctionIndex, - MiddlewareError, MiddlewareReaderState, ModuleMiddleware, Mutability, Type, + AsContextMut, ExportIndex, FunctionMiddleware, GlobalInit, GlobalType, Instance, + LocalFunctionIndex, MiddlewareError, MiddlewareReaderState, ModuleMiddleware, Mutability, Type, }; use wasmer_types::{GlobalIndex, ModuleInfo}; @@ -281,12 +281,15 @@ impl u64 + Send + Sync> FunctionMiddleware for FunctionMeter /// matches!(get_remaining_points(instance), MeteringPoints::Remaining(points) if points > 0) /// } /// ``` -pub fn get_remaining_points(instance: &Instance) -> MeteringPoints { +pub fn get_remaining_points( + mut ctx: impl AsContextMut, + instance: &Instance, +) -> MeteringPoints { let exhausted: i32 = instance .exports .get_global("wasmer_metering_points_exhausted") .expect("Can't get `wasmer_metering_points_exhausted` from Instance") - .get() + .get(&mut ctx) .try_into() .expect("`wasmer_metering_points_exhausted` from Instance has wrong type"); @@ -298,7 +301,7 @@ pub fn get_remaining_points(instance: &Instance) -> MeteringPoints { .exports .get_global("wasmer_metering_remaining_points") .expect("Can't get `wasmer_metering_remaining_points` from Instance") - .get() + .get(&mut ctx) .try_into() .expect("`wasmer_metering_remaining_points` from Instance has wrong type"); @@ -331,19 +334,23 @@ pub fn get_remaining_points(instance: &Instance) -> MeteringPoints { /// set_remaining_points(instance, new_limit); /// } /// ``` -pub fn set_remaining_points(instance: &Instance, points: u64) { +pub fn set_remaining_points( + mut ctx: impl AsContextMut, + instance: &Instance, + points: u64, +) { instance .exports .get_global("wasmer_metering_remaining_points") .expect("Can't get `wasmer_metering_remaining_points` from Instance") - .set(points.into()) + .set(&mut ctx, points.into()) .expect("Can't set `wasmer_metering_remaining_points` in Instance"); instance .exports .get_global("wasmer_metering_points_exhausted") .expect("Can't get `wasmer_metering_points_exhausted` from Instance") - .set(0i32.into()) + .set(&mut ctx, 0i32.into()) .expect("Can't set `wasmer_metering_points_exhausted` in Instance"); } @@ -352,7 +359,10 @@ mod tests { use super::*; use std::sync::Arc; - use wasmer::{imports, wat2wasm, CompilerConfig, Cranelift, Module, Store, Universal}; + use wasmer::{ + imports, wat2wasm, AsContextMut, CompilerConfig, Context, Cranelift, Module, Store, + TypedFunction, Universal, + }; fn cost_function(operator: &Operator) -> u64 { match operator { @@ -385,11 +395,12 @@ mod tests { compiler_config.push_middleware(metering); let store = Store::new_with_engine(&Universal::new(compiler_config).engine()); let module = Module::new(&store, bytecode()).unwrap(); + let mut ctx = Context::new(module.store(), ()); // Instantiate - let instance = Instance::new(&module, &imports! {}).unwrap(); + let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(10) ); @@ -399,28 +410,31 @@ mod tests { // * `local.get $value` is a `Operator::LocalGet` which costs 1 point; // * `i32.const` is a `Operator::I32Const` which costs 1 point; // * `i32.add` is a `Operator::I32Add` which costs 2 points. - let add_one = instance + let add_one: TypedFunction = instance .exports .get_function("add_one") .unwrap() - .native::() + .native(&ctx) .unwrap(); - add_one.call(1).unwrap(); + add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(6) ); // Second call - add_one.call(1).unwrap(); + add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(2) ); // Third call fails due to limit - assert!(add_one.call(1).is_err()); - assert_eq!(get_remaining_points(&instance), MeteringPoints::Exhausted); + assert!(add_one.call(&mut ctx.as_context_mut(), 1).is_err()); + assert_eq!( + get_remaining_points(ctx.as_context_mut(), &instance), + MeteringPoints::Exhausted + ); } #[test] @@ -430,49 +444,53 @@ mod tests { compiler_config.push_middleware(metering); let store = Store::new_with_engine(&Universal::new(compiler_config).engine()); let module = Module::new(&store, bytecode()).unwrap(); + let mut ctx = Context::new(module.store(), ()); // Instantiate - let instance = Instance::new(&module, &imports! {}).unwrap(); + let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(10) ); - let add_one = instance + let add_one: TypedFunction = instance .exports .get_function("add_one") .unwrap() - .native::() + .native(&ctx) .unwrap(); // Increase a bit to have enough for 3 calls - set_remaining_points(&instance, 12); + set_remaining_points(ctx.as_context_mut(), &instance, 12); // Ensure we can use the new points now - add_one.call(1).unwrap(); + add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(8) ); - add_one.call(1).unwrap(); + add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(4) ); - add_one.call(1).unwrap(); + add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(0) ); - assert!(add_one.call(1).is_err()); - assert_eq!(get_remaining_points(&instance), MeteringPoints::Exhausted); + assert!(add_one.call(&mut ctx.as_context_mut(), 1).is_err()); + assert_eq!( + get_remaining_points(ctx.as_context_mut(), &instance), + MeteringPoints::Exhausted + ); // Add some points for another call - set_remaining_points(&instance, 4); + set_remaining_points(ctx.as_context_mut(), &instance, 4); assert_eq!( - get_remaining_points(&instance), + get_remaining_points(ctx.as_context_mut(), &instance), MeteringPoints::Remaining(4) ); } From 168e3302608ece46b5d74479b2e4bf464a4c012a Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 19 Jun 2022 12:07:39 +0300 Subject: [PATCH 11/24] Renamed `get_native_function` to `get_typed_function`, marked former as deprecated. --- CHANGELOG.md | 1 + examples/early_exit.rs | 2 +- examples/exports_memory.rs | 2 +- examples/hello_world.rs | 2 +- examples/memory.rs | 6 +- examples/table.rs | 2 +- lib/api/src/js/exports.rs | 16 ++++ lib/api/src/lib.rs | 2 +- lib/api/src/sys/exports.rs | 17 ++++ lib/api/tests/js_instance.rs | 6 +- lib/api/tests/js_module.rs | 16 ++-- lib/api/tests/sys_export.rs | 12 +-- lib/api/tests/sys_externals.rs | 2 +- lib/api/tests/sys_module.rs | 16 ++-- lib/api/tests/sys_reference_types.rs | 26 +++-- lib/emscripten/src/lib.rs | 137 +++++++++++++-------------- tests/compilers/imports.rs | 10 +- tests/compilers/metering.rs | 6 +- tests/compilers/middlewares.rs | 10 +- tests/compilers/native_functions.rs | 4 +- 20 files changed, 159 insertions(+), 136 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bd4d418671..9ab9fe35c1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Looking for changes that affect our C API? See the [C API Changelog](lib/c-api/C - [#2999](https://github.com/wasmerio/wasmer/pull/2999) Allow `--invoke` CLI option for Emscripten files without a `main` function - [#2946](https://github.com/wasmerio/wasmer/pull/2946) Remove dylib,staticlib engines in favor of a single Universal engine - [#2949](https://github.com/wasmerio/wasmer/pull/2949) Switch back to using custom LLVM builds on CI +- #2892 Renamed `get_native_function` to `get_typed_function`, marked former as deprecated. ### Fixed - [#2963](https://github.com/wasmerio/wasmer/pull/2963) Remove accidental dependency on libwayland and libxcb in ClI diff --git a/examples/early_exit.rs b/examples/early_exit.rs index 63fbd2a0a8b..0206be52c2b 100644 --- a/examples/early_exit.rs +++ b/examples/early_exit.rs @@ -82,7 +82,7 @@ fn main() -> anyhow::Result<()> { // // Get the `run` function which we'll use as our entrypoint. println!("Calling `run` function..."); - let run_func: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("run")?; + let run_func: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("run")?; // When we call a function it can either succeed or fail. We expect it to fail. match run_func.call(1, 7) { diff --git a/examples/exports_memory.rs b/examples/exports_memory.rs index 8103c95ac09..0f7cb533a0e 100644 --- a/examples/exports_memory.rs +++ b/examples/exports_memory.rs @@ -52,7 +52,7 @@ fn main() -> Result<(), Box> { let load = instance .exports - .get_native_function::<(), (WasmPtr, i32)>("load")?; + .get_typed_function::<(), (WasmPtr, i32)>("load")?; // Here we go. // diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 6451460a4c2..21b16c9f367 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -82,7 +82,7 @@ fn main() -> anyhow::Result<()> { // Recall that the Wasm module exported a function named "run", this is getting // that exported function from the `Instance`. let run_func: TypedFunction<(), ()> = - instance.exports.get_native_function(&mut context, "run")?; + instance.exports.get_typed_function(&mut context, "run")?; // Finally, we call our exported Wasm function which will call our "say_hello" // function and return. diff --git a/examples/memory.rs b/examples/memory.rs index b664a6660e6..72b29c892f0 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -73,9 +73,9 @@ fn main() -> anyhow::Result<()> { // The module exports some utility functions, let's get them. // // These function will be used later in this example. - let mem_size: TypedFunction<(), i32> = instance.exports.get_native_function("mem_size")?; - let get_at: TypedFunction = instance.exports.get_native_function("get_at")?; - let set_at: TypedFunction<(i32, i32), ()> = instance.exports.get_native_function("set_at")?; + let mem_size: TypedFunction<(), i32> = instance.exports.get_typed_function("mem_size")?; + let get_at: TypedFunction = instance.exports.get_typed_function("get_at")?; + let set_at: TypedFunction<(i32, i32), ()> = instance.exports.get_typed_function("set_at")?; let memory = instance.exports.get_memory("memory")?; // We now have an instance ready to be used. diff --git a/examples/table.rs b/examples/table.rs index edad9957a9a..ac73da0a12c 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -62,7 +62,7 @@ fn main() -> anyhow::Result<()> { // The first argument is the table index and the next 2 are the 2 arguments // to be passed to the function found in the table. let call_via_table: TypedFunction<(i32, i32, i32), i32> = - instance.exports.get_native_function("call_callback")?; + instance.exports.get_typed_function("call_callback")?; // And then call it with table index 1 and arguments 2 and 7. let result = call_via_table.call(1, 2, 7)?; diff --git a/lib/api/src/js/exports.rs b/lib/api/src/js/exports.rs index 9e2f1aab840..5837820caaf 100644 --- a/lib/api/src/js/exports.rs +++ b/lib/api/src/js/exports.rs @@ -134,11 +134,27 @@ impl Exports { self.get(name) } + #[deprecated( + since = "3.0.0", + note = "get_native_function() has been renamed to get_typed_function(), just like NativeFunc has been renamed to TypedFunction." + )] /// Get an export as a `TypedFunction`. pub fn get_native_function( &self, name: &str, ) -> Result, ExportError> + where + Args: WasmTypeList, + Rets: WasmTypeList, + { + self.get_typed_function(name) + } + + /// Get an export as a `TypedFunction`. + pub fn get_typed_function( + &self, + name: &str, + ) -> Result, ExportError> where Args: WasmTypeList, Rets: WasmTypeList, diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index 09f4b89150b..6fdbb99f555 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -170,7 +170,7 @@ //! # fn exports_example(instance: &Instance) -> anyhow::Result<()> { //! let memory = instance.exports.get_memory("memory")?; //! let memory: &Memory = instance.exports.get("some_other_memory")?; -//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add")?; +//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; //! let result = add.call(5, 37)?; //! assert_eq!(result, 42); //! # Ok(()) diff --git a/lib/api/src/sys/exports.rs b/lib/api/src/sys/exports.rs index ca04e74b854..85381bc216d 100644 --- a/lib/api/src/sys/exports.rs +++ b/lib/api/src/sys/exports.rs @@ -134,12 +134,29 @@ impl Exports { self.get(name) } + #[deprecated( + since = "3.0.0", + note = "get_native_function() has been renamed to get_typed_function(), just like NativeFunc has been renamed to TypedFunction." + )] /// Get an export as a `TypedFunction`. pub fn get_native_function( &self, ctx: &impl AsContextRef, name: &str, ) -> Result, ExportError> + where + Args: WasmTypeList, + Rets: WasmTypeList, + { + self.get_typed_function(ctx, name) + } + + /// Get an export as a `TypedFunction`. + pub fn get_typed_function( + &self, + ctx: &impl AsContextRef, + name: &str, + ) -> Result, ExportError> where Args: WasmTypeList, Rets: WasmTypeList, diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs index ef524fff137..00a4bc5666d 100644 --- a/lib/api/tests/js_instance.rs +++ b/lib/api/tests/js_instance.rs @@ -610,7 +610,7 @@ mod js { let instance = Instance::new(&module, &import_object).unwrap(); let add_one: TypedFunction = - instance.exports.get_native_function("add_one").unwrap(); + instance.exports.get_typed_function("add_one").unwrap(); assert_eq!(add_one.call(1), Ok(2)); } @@ -646,7 +646,7 @@ mod js { let instance = Instance::new(&module, &import_object).unwrap(); let run_func: TypedFunction<(i32, i32), i32> = - instance.exports.get_native_function("run").unwrap(); + instance.exports.get_typed_function("run").unwrap(); assert!(run_func.call(1, 7).is_err(), "Expected early termination",); let run_func = instance.exports.get_function("run").unwrap(); @@ -725,7 +725,7 @@ mod js { } let run_func: TypedFunction<(i32, i32), i32> = - instance.exports.get_native_function("run").unwrap(); + instance.exports.get_typed_function("run").unwrap(); test_result(run_func.call(1, 7)); let run_func = instance.exports.get_function("run").unwrap(); diff --git a/lib/api/tests/js_module.rs b/lib/api/tests/js_module.rs index 71b376c7773..a1c46e40a1a 100644 --- a/lib/api/tests/js_module.rs +++ b/lib/api/tests/js_module.rs @@ -251,35 +251,35 @@ mod js { // let f1: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func1") + // .get_typed_function("call_host_func1") // .unwrap(); // let f2: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func2") + // .get_typed_function("call_host_func2") // .unwrap(); // let f3: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func3") + // .get_typed_function("call_host_func3") // .unwrap(); // let f4: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func4") + // .get_typed_function("call_host_func4") // .unwrap(); // let f5: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func5") + // .get_typed_function("call_host_func5") // .unwrap(); // let f6: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func6") + // .get_typed_function("call_host_func6") // .unwrap(); // let f7: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func7") + // .get_typed_function("call_host_func7") // .unwrap(); // let f8: TypedFunction<(), ()> = instance // .exports - // .get_native_function("call_host_func8") + // .get_typed_function("call_host_func8") // .unwrap(); // f1.call().unwrap(); diff --git a/lib/api/tests/sys_export.rs b/lib/api/tests/sys_export.rs index aed5c51f0b8..ca9a13850a7 100644 --- a/lib/api/tests/sys_export.rs +++ b/lib/api/tests/sys_export.rs @@ -139,7 +139,7 @@ mod sys { assert_eq!(is_memory_instance_ref_strong(mem), Some(true)); } - let f: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_fn")?; + let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; f.call()?; f }; @@ -183,7 +183,7 @@ mod sys { assert_eq!(is_global_instance_ref_strong(global), Some(true)); } - let f: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_fn")?; + let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; f.call()?; f }; @@ -227,7 +227,7 @@ mod sys { assert_eq!(is_table_instance_ref_strong(table), Some(true)); } - let f: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_fn")?; + let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; f.call()?; f }; @@ -271,7 +271,7 @@ mod sys { assert_eq!(is_function_instance_ref_strong(function), Some(true)); } - let f: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_fn")?; + let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; f.call()?; f }; @@ -321,14 +321,14 @@ mod sys { { let function: TypedFunction<(), ()> = - instance.exports.get_native_function("call_host_fn")?; + instance.exports.get_typed_function("call_host_fn")?; assert_eq!( is_native_function_instance_ref_strong(&function), Some(true) ); } - let f: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_fn")?; + let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; f.call()?; f }; diff --git a/lib/api/tests/sys_externals.rs b/lib/api/tests/sys_externals.rs index baad342f8cf..45ad77da476 100644 --- a/lib/api/tests/sys_externals.rs +++ b/lib/api/tests/sys_externals.rs @@ -396,7 +396,7 @@ mod sys { let f = { let module = Module::new(&store, wat)?; let instance = Instance::new(&module, &imports! {})?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("sum")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("sum")?; assert_eq!(f.call(4, 5)?, 9); f diff --git a/lib/api/tests/sys_module.rs b/lib/api/tests/sys_module.rs index c8f939f4c23..1b0bbf27d71 100644 --- a/lib/api/tests/sys_module.rs +++ b/lib/api/tests/sys_module.rs @@ -228,14 +228,14 @@ mod sys { }; let instance = Instance::new(&module, &imports)?; - let f1: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func1")?; - let f2: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func2")?; - let f3: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func3")?; - let f4: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func4")?; - let f5: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func5")?; - let f6: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func6")?; - let f7: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func7")?; - let f8: TypedFunction<(), ()> = instance.exports.get_native_function("call_host_func8")?; + let f1: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func1")?; + let f2: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func2")?; + let f3: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func3")?; + let f4: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func4")?; + let f5: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func5")?; + let f6: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func6")?; + let f7: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func7")?; + let f8: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func8")?; f1.call()?; f2.call()?; diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs index bc424b47265..809103bfaca 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/sys_reference_types.rs @@ -116,7 +116,7 @@ mod sys { { let f: TypedFunction<(), i32> = instance .exports - .get_native_function("call_host_func_with_wasm_func")?; + .get_typed_function("call_host_func_with_wasm_func")?; let result = f.call()?; assert_eq!(result, 63); } @@ -183,7 +183,7 @@ mod sys { panic!("result is not an extern ref!"); } - let f: TypedFunction<(), ExternRef> = instance.exports.get_native_function(run)?; + let f: TypedFunction<(), ExternRef> = instance.exports.get_typed_function(run)?; let result: ExternRef = f.call()?; assert!(result.is_null()); } @@ -200,7 +200,7 @@ mod sys { } let f: TypedFunction<(), ExternRef> = - instance.exports.get_native_function(get_hashmap)?; + instance.exports.get_typed_function(get_hashmap)?; let result: ExternRef = f.call()?; let inner: &HashMap = result.downcast().unwrap(); @@ -222,7 +222,7 @@ mod sys { )"#; let module = Module::new(&store, wat)?; let instance = Instance::new(&module, &imports! {})?; - let f: TypedFunction = instance.exports.get_native_function("drop")?; + let f: TypedFunction = instance.exports.get_typed_function("drop")?; let er = ExternRef::new(3u32); f.call(er.clone())?; @@ -316,7 +316,7 @@ mod sys { let instance = Instance::new(&module, &imports! {})?; let f: TypedFunction<(ExternRef, i32), ExternRef> = - instance.exports.get_native_function("insert_into_table")?; + instance.exports.get_typed_function("insert_into_table")?; let er = ExternRef::new(3usize); @@ -359,7 +359,7 @@ mod sys { assert_eq!(er.strong_count(), 2); } let get_from_global: TypedFunction<(), ExternRef> = - instance.exports.get_native_function("get_from_global")?; + instance.exports.get_typed_function("get_from_global")?; let er = get_from_global.call()?; assert_eq!(er.strong_count(), 2); @@ -383,7 +383,7 @@ mod sys { let instance = Instance::new(&module, &imports! {})?; let pass_extern_ref: TypedFunction = - instance.exports.get_native_function("pass_extern_ref")?; + instance.exports.get_typed_function("pass_extern_ref")?; let er = ExternRef::new(3usize); assert_eq!(er.strong_count(), 1); @@ -411,14 +411,12 @@ mod sys { let module = Module::new(&store, wat)?; let instance = Instance::new(&module, &imports! {})?; - let grow_table_with_ref: TypedFunction<(ExternRef, i32), i32> = instance - .exports - .get_native_function("grow_table_with_ref")?; - let fill_table_with_ref: TypedFunction<(ExternRef, i32, i32), ()> = instance - .exports - .get_native_function("fill_table_with_ref")?; + let grow_table_with_ref: TypedFunction<(ExternRef, i32), i32> = + instance.exports.get_typed_function("grow_table_with_ref")?; + let fill_table_with_ref: TypedFunction<(ExternRef, i32, i32), ()> = + instance.exports.get_typed_function("fill_table_with_ref")?; let copy_into_table2: TypedFunction<(), ()> = - instance.exports.get_native_function("copy_into_table2")?; + instance.exports.get_typed_function("copy_into_table2")?; let table1: &Table = instance.exports.get_table("table1")?; let table2: &Table = instance.exports.get_table("table2")?; diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 243600ad95b..5585e2bcbdc 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -602,234 +602,225 @@ pub fn run_emscripten_instance( env.set_memory(globals.memory.clone()); // get emscripten export let mut emfuncs = EmscriptenFunctions::new(); - if let Ok(func) = instance.exports.get_native_function(&ctx, "malloc") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "malloc") { emfuncs.malloc = Some(func); - } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_malloc") { + } else if let Ok(func) = instance.exports.get_typed_function(&ctx, "_malloc") { emfuncs.malloc = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "free") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "free") { emfuncs.free = Some(func); - } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_free") { + } else if let Ok(func) = instance.exports.get_typed_function(&ctx, "_free") { emfuncs.free = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "memalign") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "memalign") { emfuncs.memalign = Some(func); - } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_memalign") { + } else if let Ok(func) = instance.exports.get_typed_function(&ctx, "_memalign") { emfuncs.memalign = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "memset") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "memset") { emfuncs.memset = Some(func); - } else if let Ok(func) = instance.exports.get_native_function(&ctx, "_memset") { + } else if let Ok(func) = instance.exports.get_typed_function(&ctx, "_memset") { emfuncs.memset = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "stackAlloc") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "stackAlloc") { emfuncs.stack_alloc = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_i") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_i") { emfuncs.dyn_call_i = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_ii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_ii") { emfuncs.dyn_call_ii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iii") { emfuncs.dyn_call_iii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iiii") { emfuncs.dyn_call_iiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iifi") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iifi") { emfuncs.dyn_call_iifi = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_v") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_v") { emfuncs.dyn_call_v = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vi") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vi") { emfuncs.dyn_call_vi = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vii") { emfuncs.dyn_call_vii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viii") { emfuncs.dyn_call_viii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viiii") { emfuncs.dyn_call_viiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_dii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_dii") { emfuncs.dyn_call_dii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_diiii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_diiii") { emfuncs.dyn_call_diiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiiii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iiiii") { emfuncs.dyn_call_iiiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiiiii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iiiiii") { emfuncs.dyn_call_iiiiii = Some(func); } - if let Ok(func) = instance - .exports - .get_native_function(&ctx, "dynCall_iiiiiii") - { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iiiiiii") { emfuncs.dyn_call_iiiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_iiiiiiii") + .get_typed_function(&ctx, "dynCall_iiiiiiii") { emfuncs.dyn_call_iiiiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_iiiiiiiii") + .get_typed_function(&ctx, "dynCall_iiiiiiiii") { emfuncs.dyn_call_iiiiiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_iiiiiiiiii") + .get_typed_function(&ctx, "dynCall_iiiiiiiiii") { emfuncs.dyn_call_iiiiiiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_iiiiiiiiiii") + .get_typed_function(&ctx, "dynCall_iiiiiiiiiii") { emfuncs.dyn_call_iiiiiiiiiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vd") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vd") { emfuncs.dyn_call_vd = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiiii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viiiii") { emfuncs.dyn_call_viiiii = Some(func); } - if let Ok(func) = instance - .exports - .get_native_function(&ctx, "dynCall_viiiiii") - { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viiiiii") { emfuncs.dyn_call_viiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_viiiiiii") + .get_typed_function(&ctx, "dynCall_viiiiiii") { emfuncs.dyn_call_viiiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_viiiiiiii") + .get_typed_function(&ctx, "dynCall_viiiiiiii") { emfuncs.dyn_call_viiiiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_viiiiiiiii") + .get_typed_function(&ctx, "dynCall_viiiiiiiii") { emfuncs.dyn_call_viiiiiiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_viiiiiiiiii") + .get_typed_function(&ctx, "dynCall_viiiiiiiiii") { emfuncs.dyn_call_viiiiiiiiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iij") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iij") { emfuncs.dyn_call_iij = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iji") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iji") { emfuncs.dyn_call_iji = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiji") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iiji") { emfuncs.dyn_call_iiji = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_iiijj") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_iiijj") { emfuncs.dyn_call_iiijj = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_j") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_j") { emfuncs.dyn_call_j = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_ji") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_ji") { emfuncs.dyn_call_ji = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_jii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_jii") { emfuncs.dyn_call_jii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_jij") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_jij") { emfuncs.dyn_call_jij = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_jjj") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_jjj") { emfuncs.dyn_call_jjj = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiij") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viiij") { emfuncs.dyn_call_viiij = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_viiijiiii") + .get_typed_function(&ctx, "dynCall_viiijiiii") { emfuncs.dyn_call_viiijiiii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_viiijiiiiii") + .get_typed_function(&ctx, "dynCall_viiijiiiiii") { emfuncs.dyn_call_viiijiiiiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viij") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viij") { emfuncs.dyn_call_viij = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viiji") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viiji") { emfuncs.dyn_call_viiji = Some(func); } - if let Ok(func) = instance - .exports - .get_native_function(&ctx, "dynCall_viijiii") - { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viijiii") { emfuncs.dyn_call_viijiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viijj") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viijj") { emfuncs.dyn_call_viijj = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vj") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vj") { emfuncs.dyn_call_vj = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vjji") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vjji") { emfuncs.dyn_call_vjji = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vij") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vij") { emfuncs.dyn_call_vij = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viji") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viji") { emfuncs.dyn_call_viji = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vijiii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vijiii") { emfuncs.dyn_call_vijiii = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vijj") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vijj") { emfuncs.dyn_call_vijj = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viid") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viid") { emfuncs.dyn_call_viid = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_vidd") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_vidd") { emfuncs.dyn_call_vidd = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "dynCall_viidii") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "dynCall_viidii") { emfuncs.dyn_call_viidii = Some(func); } if let Ok(func) = instance .exports - .get_native_function(&ctx, "dynCall_viidddddddd") + .get_typed_function(&ctx, "dynCall_viidddddddd") { emfuncs.dyn_call_viidddddddd = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "stackSave") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "stackSave") { emfuncs.stack_save = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "stackRestore") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "stackRestore") { emfuncs.stack_restore = Some(func); } - if let Ok(func) = instance.exports.get_native_function(&ctx, "setThrew") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "setThrew") { emfuncs.set_threw = Some(func); } ctx.data_mut().set_functions(emfuncs); diff --git a/tests/compilers/imports.rs b/tests/compilers/imports.rs index 869e330c6c5..8c8ab7db07c 100644 --- a/tests/compilers/imports.rs +++ b/tests/compilers/imports.rs @@ -341,7 +341,7 @@ fn dynamic_function_with_env_wasmer_env_init_works(config: crate::Config) -> Res }, }, )?; - let f: TypedFunction<(), ()> = instance.exports.get_native_function("main")?; + let f: TypedFunction<(), ()> = instance.exports.get_typed_function("main")?; f.call()?; Ok(()) } @@ -381,12 +381,12 @@ fn multi_use_host_fn_manages_memory_correctly(config: crate::Config) -> Result<( let instance1 = Instance::new(&module, &imports)?; let instance2 = Instance::new(&module, &imports)?; { - let f1: TypedFunction<(), ()> = instance1.exports.get_native_function("main")?; + let f1: TypedFunction<(), ()> = instance1.exports.get_typed_function("main")?; f1.call()?; } drop(instance1); { - let f2: TypedFunction<(), ()> = instance2.exports.get_native_function("main")?; + let f2: TypedFunction<(), ()> = instance2.exports.get_typed_function("main")?; f2.call()?; } drop(instance2); @@ -425,8 +425,8 @@ fn instance_local_memory_lifetime(config: crate::Config) -> Result<()> { }, }; let instance = Instance::new(&module, &imports)?; - let set_at: TypedFunction<(i32, i32), ()> = instance.exports.get_native_function("set_at")?; - let get_at: TypedFunction = instance.exports.get_native_function("get_at")?; + let set_at: TypedFunction<(i32, i32), ()> = instance.exports.get_typed_function("set_at")?; + let get_at: TypedFunction = instance.exports.get_typed_function("get_at")?; set_at.call(200, 123)?; assert_eq!(get_at.call(200)?, 123); diff --git a/tests/compilers/metering.rs b/tests/compilers/metering.rs index 6732aa4fb33..518552412f7 100644 --- a/tests/compilers/metering.rs +++ b/tests/compilers/metering.rs @@ -25,7 +25,7 @@ fn run_add_with_limit(mut config: crate::Config, limit: u64) -> Result<()> { let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; f.call(4, 6)?; Ok(()) } @@ -56,7 +56,7 @@ fn run_loop(mut config: crate::Config, limit: u64, iter_count: i32) -> Result<() let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction = instance.exports.get_native_function("test")?; + let f: TypedFunction = instance.exports.get_typed_function("test")?; f.call(iter_count)?; Ok(()) } @@ -159,7 +159,7 @@ fn complex_loop(mut config: crate::Config) -> Result<()> { let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add_to")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add_to")?; // FIXME: Since now a metering error is signaled with an `unreachable`, it is impossible to verify // the error type. Fix this later. diff --git a/tests/compilers/middlewares.rs b/tests/compilers/middlewares.rs index bc4b628c5a1..0690a27c065 100644 --- a/tests/compilers/middlewares.rs +++ b/tests/compilers/middlewares.rs @@ -104,7 +104,7 @@ fn middleware_basic(mut config: crate::Config) -> Result<()> { let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; let result = f.call(4, 6)?; assert_eq!(result, 24); Ok(()) @@ -127,7 +127,7 @@ fn middleware_one_to_multi(mut config: crate::Config) -> Result<()> { let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; let result = f.call(4, 6)?; assert_eq!(result, 25); Ok(()) @@ -151,7 +151,7 @@ fn middleware_multi_to_one(mut config: crate::Config) -> Result<()> { let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("testfunc")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("testfunc")?; let result = f.call(10, 20)?; assert_eq!(result, 10); Ok(()) @@ -175,7 +175,7 @@ fn middleware_chain_order_1(mut config: crate::Config) -> Result<()> { let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; let result = f.call(4, 6)?; assert_eq!(result, 24); Ok(()) @@ -199,7 +199,7 @@ fn middleware_chain_order_2(mut config: crate::Config) -> Result<()> { let instance = Instance::new(&module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; let result = f.call(4, 6)?; assert_eq!(result, 48); Ok(()) diff --git a/tests/compilers/native_functions.rs b/tests/compilers/native_functions.rs index 3c81d66b1e7..bb6fba0a006 100644 --- a/tests/compilers/native_functions.rs +++ b/tests/compilers/native_functions.rs @@ -55,7 +55,7 @@ fn native_function_works_for_wasm(config: crate::Config) -> anyhow::Result<()> { let instance = Instance::new(&module, &import_object)?; { - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_native_function("add")?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; let result = f.call(4, 6)?; assert_eq!(result, 10); } @@ -152,7 +152,7 @@ fn non_native_functions_and_closures_with_no_env_work(config: crate::Config) -> let instance = Instance::new(&module, &import_object)?; let test: TypedFunction<(i32, i32, i32, i32, i32), i32> = - instance.exports.get_native_function("test")?; + instance.exports.get_typed_function("test")?; let result = test.call(2, 3, 4, 5, 6)?; let manually_computed_result = 6 * (5 * (4 * (3 * 2 * 20) * 10 * 20)) * 10; From 6c089bbc45e4864a68393522169059a17d625b14 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 21 Jun 2022 16:27:06 +0300 Subject: [PATCH 12/24] Port JS API to new Context API --- lib/api/Cargo.toml | 1 + lib/api/src/js/context.rs | 449 ++++++++++++++++ lib/api/src/js/env.rs | 219 -------- lib/api/src/js/error.rs | 61 +++ lib/api/src/js/export.rs | 105 ++-- lib/api/src/js/exports.rs | 42 +- lib/api/src/js/externals/function.rs | 775 +++++++++++---------------- lib/api/src/js/externals/global.rs | 163 +++--- lib/api/src/js/externals/memory.rs | 229 +++++--- lib/api/src/js/externals/mod.rs | 65 ++- lib/api/src/js/externals/table.rs | 122 +++-- lib/api/src/js/imports.rs | 33 +- lib/api/src/js/instance.rs | 101 +--- lib/api/src/js/js_import_object.rs | 20 +- lib/api/src/js/mem_access.rs | 47 +- lib/api/src/js/mod.rs | 22 +- lib/api/src/js/module.rs | 35 +- lib/api/src/js/native.rs | 57 +- lib/api/src/js/native_type.rs | 160 ++++++ lib/api/src/js/ptr.rs | 36 +- lib/api/src/js/types.rs | 37 +- lib/api/src/js/value.rs | 423 +++++++++++++++ lib/api/src/lib.rs | 1 - lib/api/src/sys/context.rs | 2 +- lib/api/src/sys/exports.rs | 2 +- lib/api/tests/js_externals.rs | 330 ++++++------ lib/api/tests/js_instance.rs | 440 ++++++++------- lib/api/tests/sys_export.rs | 35 +- lib/api/tests/sys_externals.rs | 34 +- lib/api/tests/sys_instance.rs | 4 +- lib/api/tests/sys_reference_types.rs | 4 +- lib/types/src/lib.rs | 11 + lib/wasi/src/lib.rs | 18 +- lib/wasi/tests/stdio.rs | 41 +- 34 files changed, 2509 insertions(+), 1615 deletions(-) create mode 100644 lib/api/src/js/context.rs delete mode 100644 lib/api/src/js/env.rs create mode 100644 lib/api/src/js/native_type.rs create mode 100644 lib/api/src/js/value.rs diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 5883ca598fa..2ff837c00f9 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -56,6 +56,7 @@ anyhow = "1.0" wasmer-types = { path = "../types", version = "=2.3.0", default-features = false, features = ["std"] } wasm-bindgen = "0.2.74" js-sys = "0.3.51" +#web-sys = { version = "0.3.51", features = [ "console" ] } wasmer-derive = { path = "../derive", version = "=2.3.0" } # - Optional dependencies for `js`. wasmparser = { version = "0.83", default-features = false, optional = true } diff --git a/lib/api/src/js/context.rs b/lib/api/src/js/context.rs new file mode 100644 index 00000000000..9823abbe7cb --- /dev/null +++ b/lib/api/src/js/context.rs @@ -0,0 +1,449 @@ +#![allow(dead_code)] +use crate::Store; + +/// We require the context to have a fixed memory address for its lifetime since +/// various bits of the VM have raw pointers that point back to it. Hence we +/// wrap the actual context in a box. +pub(crate) struct ContextInner { + pub(crate) objects: ContextObjects, + pub(crate) store: Store, + pub(crate) data: T, +} + +/// A context containing a set of WebAssembly instances, along with host state. +/// +/// All WebAssembly instances must exist within a context. In the majority of +/// cases each instance will have its own context, but it is possible to have +/// multiple instances in a context when these instances need to interact with +/// each other, for example sharing a memory between instances or calling +/// functions in another instance. +/// +/// The lifetimes of run-time WebAssembly objects, notably [`Instance`], +/// [`Memory`], [`Global`], [`Table`] and [`Function`] is tied to a context: +/// the backing memory for these objects is only freed when the context is +/// freed. +/// +/// The `T` generic parameter allows arbitrary data to be attached to a context. +/// This data can be accessed using the [`Context::data`] and +/// [`Context::data_mut`] methods. Host functions defined using +/// [`Function::new`] and [`Function::new_native`] receive +/// a reference to the context when they are called. +pub struct Context { + pub(crate) inner: Box>, +} + +impl Context { + /// Creates a new context with the given host state. + // TODO: Eliminate the Store type and move its functionality into Engine. + pub fn new(store: &Store, data: T) -> Self { + Self { + inner: Box::new(ContextInner { + objects: Default::default(), + store: store.clone(), + data, + }), + } + } + + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &T { + &self.inner.data + } + + /// Returns a mutable- reference to the host state in this context. + pub fn data_mut(&mut self) -> &mut T { + &mut self.inner.data + } + + /// Drops the context and returns the host state that was stored in it. + pub fn into_data(self) -> T { + self.inner.data + } + + /// Returns a reference to the `Store` of this context. + pub fn store(&self) -> &Store { + &self.inner.store + } +} + +/// A temporary handle to a [`Context`]. +pub struct ContextRef<'a, T: 'a> { + inner: &'a ContextInner, +} + +impl<'a, T> ContextRef<'a, T> { + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &'a T { + &self.inner.data + } + + /// Returns a reference to the `Store` of this context. + pub fn store(&self) -> &Store { + &self.inner.store + } + + pub(crate) fn objects(&self) -> &'a ContextObjects { + &self.inner.objects + } +} + +/// A temporary handle to a [`Context`]. +pub struct ContextMut<'a, T: 'a> { + inner: &'a mut ContextInner, +} + +impl ContextMut<'_, T> { + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &T { + &self.inner.data + } + + /// Returns a mutable- reference to the host state in this context. + pub fn data_mut(&mut self) -> &mut T { + &mut self.inner.data + } + + pub(crate) fn objects_mut(&mut self) -> &mut ContextObjects { + &mut self.inner.objects + } + + /// Returns a reference to the `Store` of this context. + pub fn store(&self) -> &Store { + &self.inner.store + } + + /// Returns the raw pointer of the context + pub(crate) fn as_raw(&self) -> *mut ContextInner { + self.inner as *const ContextInner as *mut ContextInner + } + + /// Constructs the context from the raw pointer + pub(crate) unsafe fn from_raw(raw: *mut ContextInner) -> Self { + Self { inner: &mut *raw } + } +} + +/// Helper trait for a value that is convertible to a [`ContextRef`]. +pub trait AsContextRef { + /// Host state associated with the [`Context`]. + type Data; + + /// Returns a `ContextRef` pointing to the underlying context. + fn as_context_ref(&self) -> ContextRef<'_, Self::Data>; +} + +/// Helper trait for a value that is convertible to a [`ContextMut`]. +pub trait AsContextMut: AsContextRef { + /// Returns a `ContextMut` pointing to the underlying context. + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data>; +} + +impl AsContextRef for Context { + type Data = T; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + ContextRef { inner: &self.inner } + } +} +impl AsContextMut for Context { + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { + ContextMut { + inner: &mut self.inner, + } + } +} +impl AsContextRef for ContextRef<'_, T> { + type Data = T; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + ContextRef { inner: self.inner } + } +} +impl AsContextRef for ContextMut<'_, T> { + type Data = T; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + ContextRef { inner: self.inner } + } +} +impl AsContextMut for ContextMut<'_, T> { + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { + ContextMut { inner: self.inner } + } +} +impl AsContextRef for &'_ T { + type Data = T::Data; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + T::as_context_ref(*self) + } +} +impl AsContextRef for &'_ mut T { + type Data = T::Data; + + fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { + T::as_context_ref(*self) + } +} +impl AsContextMut for &'_ mut T { + fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { + T::as_context_mut(*self) + } +} + +pub use objects::*; +mod objects { + use crate::js::export::{VMFunction, VMGlobal, VMMemory, VMTable}; + use std::{ + cell::UnsafeCell, + fmt, + marker::PhantomData, + num::{NonZeroU64, NonZeroUsize}, + ptr::NonNull, + sync::atomic::{AtomicU64, Ordering}, + }; + + /// Unique ID to identify a context. + /// + /// Every handle to an object managed by a context also contains the ID of the + /// context. This is used to check that a handle is always used with the + /// correct context. + #[derive(Debug, Copy, Clone, Eq, PartialEq)] + pub struct ContextId(NonZeroU64); + + impl Default for ContextId { + // Allocates a unique ID for a new context. + fn default() -> Self { + // No overflow checking is needed here: overflowing this would take + // thousands of years. + static NEXT_ID: AtomicU64 = AtomicU64::new(1); + Self(NonZeroU64::new(NEXT_ID.fetch_add(1, Ordering::Relaxed)).unwrap()) + } + } + + /// Trait to represent an object managed by a context. This is implemented on + /// the VM types managed by the context. + pub trait ContextObject: Sized { + fn list(ctx: &ContextObjects) -> &Vec; + fn list_mut(ctx: &mut ContextObjects) -> &mut Vec; + } + + macro_rules! impl_context_object { + ($($field:ident => $ty:ty,)*) => { + $( + impl ContextObject for $ty { + fn list(ctx: &ContextObjects) -> &Vec { + &ctx.$field + } + fn list_mut(ctx: &mut ContextObjects) -> &mut Vec { + &mut ctx.$field + } + } + )* + }; +} + + impl_context_object! { + functions => VMFunction, + tables => VMTable, + globals => VMGlobal, + memories => VMMemory, + instances => js_sys::WebAssembly::Instance, + } + + /// Set of objects managed by a context. + #[derive(Default)] + pub struct ContextObjects { + id: ContextId, + memories: Vec, + tables: Vec, + globals: Vec, + functions: Vec, + instances: Vec, + } + + impl ContextObjects { + /// Returns the ID of this context. + pub fn id(&self) -> ContextId { + self.id + } + + /// Returns a pair of mutable references from two handles. + /// + /// Panics if both handles point to the same object. + pub fn get_2_mut( + &mut self, + a: InternalContextHandle, + b: InternalContextHandle, + ) -> (&mut T, &mut T) { + assert_ne!(a.index(), b.index()); + let list = T::list_mut(self); + if a.index() < b.index() { + let (low, high) = list.split_at_mut(b.index()); + (&mut low[a.index()], &mut high[0]) + } else { + let (low, high) = list.split_at_mut(a.index()); + (&mut high[0], &mut low[a.index()]) + } + } + } + + /// Handle to an object managed by a context. + /// + /// Internally this is just an integer index into a context. A reference to the + /// context must be passed in separately to access the actual object. + pub struct ContextHandle { + id: ContextId, + internal: InternalContextHandle, + } + + impl core::cmp::PartialEq for ContextHandle { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } + } + impl Clone for ContextHandle { + fn clone(&self) -> Self { + Self { + id: self.id, + internal: self.internal, + } + } + } + + impl fmt::Debug for ContextHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ContextHandle") + .field("id", &self.id) + .field("internal", &self.internal.index()) + .finish() + } + } + + impl ContextHandle { + /// Moves the given object into a context and returns a handle to it. + pub fn new(ctx: &mut ContextObjects, val: T) -> Self { + Self { + id: ctx.id, + internal: InternalContextHandle::new(ctx, val), + } + } + + /// Returns a reference to the object that this handle points to. + pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { + assert_eq!(self.id, ctx.id, "object used with the wrong context"); + self.internal.get(ctx) + } + + /// Returns a mutable reference to the object that this handle points to. + pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { + assert_eq!(self.id, ctx.id, "object used with the wrong context"); + self.internal.get_mut(ctx) + } + + /// Returns the internal handle contains within this handle. + pub fn internal_handle(&self) -> InternalContextHandle { + self.internal + } + + /// Returns the ID of the context associated with the handle. + pub fn context_id(&self) -> ContextId { + self.id + } + + /// Constructs a `ContextHandle` from a `ContextId` and an `InternalContextHandle`. + /// + /// # Safety + /// Handling `InternalContextHandle` values is unsafe because they do not track context ID. + pub unsafe fn from_internal(id: ContextId, internal: InternalContextHandle) -> Self { + Self { id, internal } + } + } + + /// Internal handle to an object owned by the current context. + /// + /// Unlike `ContextHandle` this does not track the context ID: it is only + /// intended to be used within objects already owned by a context. + #[repr(transparent)] + pub struct InternalContextHandle { + // Use a NonZero here to reduce the size of Option. + idx: NonZeroUsize, + marker: PhantomData T>, + } + + impl Clone for InternalContextHandle { + fn clone(&self) -> Self { + *self + } + } + impl Copy for InternalContextHandle {} + + impl fmt::Debug for InternalContextHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("InternalContextHandle") + .field("idx", &self.idx) + .finish() + } + } + impl PartialEq for InternalContextHandle { + fn eq(&self, other: &Self) -> bool { + self.idx == other.idx + } + } + impl Eq for InternalContextHandle {} + + impl InternalContextHandle { + /// Moves the given object into a context and returns a handle to it. + pub fn new(ctx: &mut ContextObjects, val: T) -> Self { + let list = T::list_mut(ctx); + let idx = NonZeroUsize::new(list.len() + 1).unwrap(); + list.push(val); + Self { + idx, + marker: PhantomData, + } + } + + /// Returns a reference to the object that this handle points to. + pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { + &T::list(ctx)[self.idx.get() - 1] + } + + /// Returns a mutable reference to the object that this handle points to. + pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { + &mut T::list_mut(ctx)[self.idx.get() - 1] + } + + pub(crate) fn index(&self) -> usize { + self.idx.get() + } + + pub(crate) fn from_index(idx: usize) -> Option { + NonZeroUsize::new(idx).map(|idx| Self { + idx, + marker: PhantomData, + }) + } + } + + /// Data used by the generated code is generally located inline within the + /// `VMContext` for items defined in an instance. Host-defined objects are + /// allocated separately and owned directly by the context. + pub enum MaybeInstanceOwned { + /// The data is owned here. + Host(Box>), + + /// The data is stored inline in the `VMContext` of an instance. + Instance(NonNull), + } + + impl MaybeInstanceOwned { + /// Returns underlying pointer to the VM data. + pub fn as_ptr(&self) -> NonNull { + match self { + MaybeInstanceOwned::Host(p) => unsafe { NonNull::new_unchecked(p.get()) }, + MaybeInstanceOwned::Instance(p) => *p, + } + } + } +} diff --git a/lib/api/src/js/env.rs b/lib/api/src/js/env.rs deleted file mode 100644 index 20921c10560..00000000000 --- a/lib/api/src/js/env.rs +++ /dev/null @@ -1,219 +0,0 @@ -use crate::js::{ExportError, Instance}; -use thiserror::Error; - -/// An error while initializing the user supplied host env with the `WasmerEnv` trait. -#[derive(Error, Debug)] -#[error("Host env initialization error: {0}")] -pub enum HostEnvInitError { - /// An error occurred when accessing an export - Export(ExportError), -} - -impl From for HostEnvInitError { - fn from(other: ExportError) -> Self { - Self::Export(other) - } -} - -/// Trait for initializing the environments passed to host functions after -/// instantiation but before execution. -/// -/// This is useful for filling an environment with data that can only be accesed -/// after instantiation. For example, exported items such as memories and -/// functions which don't exist prior to instantiation can be accessed here so -/// that host functions can use them. -/// -/// # Examples -/// -/// This trait can be derived like so: -/// -/// ``` -/// use wasmer::{WasmerEnv, LazyInit, Memory, TypedFunction}; -/// -/// #[derive(WasmerEnv, Clone)] -/// pub struct MyEnvWithNoInstanceData { -/// non_instance_data: u8, -/// } -/// -/// #[derive(WasmerEnv, Clone)] -/// pub struct MyEnvWithInstanceData { -/// non_instance_data: u8, -/// #[wasmer(export)] -/// memory: LazyInit, -/// #[wasmer(export(name = "real_name"))] -/// func: LazyInit>, -/// #[wasmer(export(optional = true, alias = "memory2", alias = "_memory2"))] -/// optional_memory: LazyInit, -/// } -/// ``` -/// -/// When deriving `WasmerEnv`, you must wrap your types to be initialized in -/// [`LazyInit`]. The derive macro will also generate helper methods of the form -/// `_ref` and `_ref_unchecked` for easy access to the -/// data. -/// -/// The valid arguments to `export` are: -/// - `name = "string"`: specify the name of this item in the Wasm module. If this is not specified, it will default to the name of the field. -/// - `optional = true`: specify whether this export is optional. Defaults to -/// `false`. Being optional means that if the export can't be found, the -/// [`LazyInit`] will be left uninitialized. -/// - `alias = "string"`: specify additional names to look for in the Wasm module. -/// `alias` may be specified multiple times to search for multiple aliases. -/// ------- -/// -/// This trait may also be implemented manually: -/// ``` -/// # use wasmer::{WasmerEnv, LazyInit, Memory, Instance, HostEnvInitError}; -/// #[derive(Clone)] -/// pub struct MyEnv { -/// memory: LazyInit, -/// } -/// -/// impl WasmerEnv for MyEnv { -/// fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> { -/// let memory: Memory = instance.exports.get_with_generics_weak("memory").unwrap(); -/// self.memory.initialize(memory.clone()); -/// Ok(()) -/// } -/// } -/// ``` -pub trait WasmerEnv { - /// The function that Wasmer will call on your type to let it finish - /// setting up the environment with data from the `Instance`. - /// - /// This function is called after `Instance` is created but before it is - /// returned to the user via `Instance::new`. - fn init_with_instance(&mut self, _instance: &Instance) -> Result<(), HostEnvInitError> { - Ok(()) - } -} - -impl WasmerEnv for u8 {} -impl WasmerEnv for i8 {} -impl WasmerEnv for u16 {} -impl WasmerEnv for i16 {} -impl WasmerEnv for u32 {} -impl WasmerEnv for i32 {} -impl WasmerEnv for u64 {} -impl WasmerEnv for i64 {} -impl WasmerEnv for u128 {} -impl WasmerEnv for i128 {} -impl WasmerEnv for f32 {} -impl WasmerEnv for f64 {} -impl WasmerEnv for usize {} -impl WasmerEnv for isize {} -impl WasmerEnv for char {} -impl WasmerEnv for bool {} -impl WasmerEnv for String {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicBool {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI8 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU8 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI16 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU16 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI32 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU32 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI64 {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicUsize {} -impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicIsize {} -impl WasmerEnv for Box { - fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> { - (&mut **self).init_with_instance(instance) - } -} - -impl WasmerEnv for ::std::sync::Arc<::std::sync::Mutex> { - fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> { - let mut guard = self.lock().unwrap(); - guard.init_with_instance(instance) - } -} - -/// Lazily init an item -pub struct LazyInit { - /// The data to be initialized - data: std::mem::MaybeUninit, - /// Whether or not the data has been initialized - initialized: bool, -} - -impl LazyInit { - /// Creates an unitialized value. - pub fn new() -> Self { - Self { - data: std::mem::MaybeUninit::uninit(), - initialized: false, - } - } - - /// # Safety - /// - The data must be initialized first - pub unsafe fn get_unchecked(&self) -> &T { - &*self.data.as_ptr() - } - - /// Get the inner data. - pub fn get_ref(&self) -> Option<&T> { - if !self.initialized { - None - } else { - Some(unsafe { self.get_unchecked() }) - } - } - - /// Sets a value and marks the data as initialized. - pub fn initialize(&mut self, value: T) -> bool { - if self.initialized { - return false; - } - unsafe { - self.data.as_mut_ptr().write(value); - } - self.initialized = true; - true - } -} - -impl std::fmt::Debug for LazyInit { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("LazyInit") - .field("data", &self.get_ref()) - .finish() - } -} - -impl Clone for LazyInit { - fn clone(&self) -> Self { - if let Some(inner) = self.get_ref() { - Self { - data: std::mem::MaybeUninit::new(inner.clone()), - initialized: true, - } - } else { - Self { - data: std::mem::MaybeUninit::uninit(), - initialized: false, - } - } - } -} - -impl Drop for LazyInit { - fn drop(&mut self) { - if self.initialized { - unsafe { - let ptr = self.data.as_mut_ptr(); - std::ptr::drop_in_place(ptr); - }; - } - } -} - -impl Default for LazyInit { - fn default() -> Self { - Self::new() - } -} - -unsafe impl Send for LazyInit {} -// I thought we could opt out of sync..., look into this -// unsafe impl !Sync for InitWithInstance {} diff --git a/lib/api/src/js/error.rs b/lib/api/src/js/error.rs index 8931d0fd6ab..5a25c99d88e 100644 --- a/lib/api/src/js/error.rs +++ b/lib/api/src/js/error.rs @@ -1,4 +1,7 @@ use crate::js::lib::std::string::String; +use crate::js::trap::RuntimeError; +#[cfg(feature = "std")] +use std::borrow::Cow; #[cfg(feature = "std")] use thiserror::Error; @@ -83,11 +86,27 @@ pub enum WasmError { #[cfg_attr(feature = "std", error("Unsupported feature: {0}"))] Unsupported(String), + /// A Javascript value could not be converted to the requested type. + #[cfg_attr(feature = "std", error("{0} doesn't match js value type {1}"))] + TypeMismatch(Cow<'static, str>, Cow<'static, str>), + /// A generic error. #[cfg_attr(feature = "std", error("{0}"))] Generic(String), } +impl From for WasmError { + fn from(err: wasm_bindgen::JsValue) -> Self { + Self::Generic( + if err.is_string() && err.as_string().filter(|s| !s.is_empty()).is_some() { + err.as_string().unwrap_or_default() + } else { + format!("Unexpected Javascript error: {:?}", err) + }, + ) + } +} + /// The Serialize error can occur when serializing a /// compiled Module into a binary. /// Copied from wasmer_compiler::SerializeError @@ -124,3 +143,45 @@ pub enum DeserializeError { #[cfg_attr(feature = "std", error(transparent))] Compiler(CompileError), } + +/// An error while instantiating a module. +/// +/// This is not a common WebAssembly error, however +/// we need to differentiate from a `LinkError` (an error +/// that happens while linking, on instantiation), a +/// Trap that occurs when calling the WebAssembly module +/// start function, and an error when initializing the user's +/// host environments. +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(Error))] +pub enum InstantiationError { + /// A linking ocurred during instantiation. + #[cfg_attr(feature = "std", error("Link error: {0}"))] + Link(String), + + /// A runtime error occured while invoking the start function + #[cfg_attr(feature = "std", error(transparent))] + Start(RuntimeError), + + /// Import from a different [`Context`]. + /// This error occurs when an import from a different context is used. + #[cfg_attr(feature = "std", error("cannot mix imports from different contexts"))] + BadContext, + + /// A generic error occured while invoking API functions + #[cfg_attr(feature = "std", error(transparent))] + Wasm(WasmError), +} + +impl From for InstantiationError { + fn from(original: WasmError) -> Self { + Self::Wasm(original) + } +} + +#[cfg(feature = "core")] +impl std::fmt::Display for InstantiationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "InstantiationError") + } +} diff --git a/lib/api/src/js/export.rs b/lib/api/src/js/export.rs index fc5f638c442..41d72145d01 100644 --- a/lib/api/src/js/export.rs +++ b/lib/api/src/js/export.rs @@ -1,12 +1,9 @@ -use crate::js::instance::Instance; +use crate::js::context::{AsContextMut, AsContextRef, InternalContextHandle}; +use crate::js::error::WasmError; use crate::js::wasm_bindgen_polyfill::Global; -use crate::js::HostEnvInitError; -use crate::js::WasmerEnv; use js_sys::Function; use js_sys::WebAssembly::{Memory, Table}; -use std::cell::RefCell; use std::fmt; -use std::sync::Arc; use wasm_bindgen::{JsCast, JsValue}; use wasmer_types::{ExternType, FunctionType, GlobalType, MemoryType, TableType}; @@ -59,31 +56,14 @@ impl VMTable { pub struct VMFunction { pub(crate) function: Function, pub(crate) ty: FunctionType, - pub(crate) environment: Option>>>, } unsafe impl Send for VMFunction {} unsafe impl Sync for VMFunction {} impl VMFunction { - pub(crate) fn new( - function: Function, - ty: FunctionType, - environment: Option>, - ) -> Self { - Self { - function, - ty, - environment: environment.map(|env| Arc::new(RefCell::new(env))), - } - } - - pub(crate) fn init_envs(&self, instance: &Instance) -> Result<(), HostEnvInitError> { - if let Some(env) = &self.environment { - let mut borrowed_env = env.borrow_mut(); - borrowed_env.init_with_instance(instance)?; - } - Ok(()) + pub(crate) fn new(function: Function, ty: FunctionType) -> Self { + Self { function, ty } } } @@ -105,67 +85,90 @@ impl fmt::Debug for VMFunction { #[derive(Debug, Clone)] pub enum Export { /// A function export value. - Function(VMFunction), + Function(InternalContextHandle), /// A table export value. - Table(VMTable), + Table(InternalContextHandle), /// A memory export value. - Memory(VMMemory), + Memory(InternalContextHandle), /// A global export value. - Global(VMGlobal), + Global(InternalContextHandle), } impl Export { /// Return the export as a `JSValue`. - pub fn as_jsvalue(&self) -> &JsValue { + pub fn as_jsvalue<'context>(&self, ctx: &'context impl AsContextRef) -> &'context JsValue { match self { - Export::Memory(js_wasm_memory) => js_wasm_memory.memory.as_ref(), - Export::Function(js_func) => js_func.function.as_ref(), - Export::Table(js_wasm_table) => js_wasm_table.table.as_ref(), - Export::Global(js_wasm_global) => js_wasm_global.global.as_ref(), + Self::Memory(js_wasm_memory) => js_wasm_memory + .get(ctx.as_context_ref().objects()) + .memory + .as_ref(), + Self::Function(js_func) => js_func + .get(ctx.as_context_ref().objects()) + .function + .as_ref(), + Self::Table(js_wasm_table) => js_wasm_table + .get(ctx.as_context_ref().objects()) + .table + .as_ref(), + Self::Global(js_wasm_global) => js_wasm_global + .get(ctx.as_context_ref().objects()) + .global + .as_ref(), } } -} -impl From<(JsValue, ExternType)> for Export { - fn from((val, extern_type): (JsValue, ExternType)) -> Export { + /// Convert a `JsValue` into an `Export` within a given `Context`. + pub fn from_js_value( + val: JsValue, + ctx: &mut impl AsContextMut, + extern_type: ExternType, + ) -> Result { match extern_type { ExternType::Memory(memory_type) => { if val.is_instance_of::() { - return Export::Memory(VMMemory::new( - val.unchecked_into::(), - memory_type, - )); + Ok(Self::Memory(InternalContextHandle::new( + &mut ctx.as_context_mut().objects_mut(), + VMMemory::new(val.unchecked_into::(), memory_type), + ))) } else { - panic!("Extern type doesn't match js value type"); + Err(WasmError::TypeMismatch( + val.js_typeof() + .as_string() + .map(Into::into) + .unwrap_or("unknown".into()), + "Memory".into(), + )) } } ExternType::Global(global_type) => { if val.is_instance_of::() { - return Export::Global(VMGlobal::new( - val.unchecked_into::(), - global_type, - )); + Ok(Self::Global(InternalContextHandle::new( + &mut ctx.as_context_mut().objects_mut(), + VMGlobal::new(val.unchecked_into::(), global_type), + ))) } else { panic!("Extern type doesn't match js value type"); } } ExternType::Function(function_type) => { if val.is_instance_of::() { - return Export::Function(VMFunction::new( - val.unchecked_into::(), - function_type, - None, - )); + Ok(Self::Function(InternalContextHandle::new( + &mut ctx.as_context_mut().objects_mut(), + VMFunction::new(val.unchecked_into::(), function_type), + ))) } else { panic!("Extern type doesn't match js value type"); } } ExternType::Table(table_type) => { if val.is_instance_of::() { - return Export::Table(VMTable::new(val.unchecked_into::
(), table_type)); + Ok(Self::Table(InternalContextHandle::new( + &mut ctx.as_context_mut().objects_mut(), + VMTable::new(val.unchecked_into::
(), table_type), + ))) } else { panic!("Extern type doesn't match js value type"); } diff --git a/lib/api/src/js/exports.rs b/lib/api/src/js/exports.rs index 5837820caaf..c25e947eb91 100644 --- a/lib/api/src/js/exports.rs +++ b/lib/api/src/js/exports.rs @@ -1,4 +1,4 @@ -use crate::js::export::Export; +use crate::js::context::AsContextRef; use crate::js::externals::{Extern, Function, Global, Memory, Table}; use crate::js::native::TypedFunction; use crate::js::WasmTypeList; @@ -141,18 +141,20 @@ impl Exports { /// Get an export as a `TypedFunction`. pub fn get_native_function( &self, + ctx: &impl AsContextRef, name: &str, ) -> Result, ExportError> where Args: WasmTypeList, Rets: WasmTypeList, { - self.get_typed_function(name) + self.get_typed_function(ctx, name) } /// Get an export as a `TypedFunction`. pub fn get_typed_function( &self, + ctx: &impl AsContextRef, name: &str, ) -> Result, ExportError> where @@ -160,12 +162,16 @@ impl Exports { Rets: WasmTypeList, { self.get_function(name)? - .native() + .native(ctx) .map_err(|_| ExportError::IncompatibleType) } /// Hack to get this working with nativefunc too - pub fn get_with_generics<'a, T, Args, Rets>(&'a self, name: &str) -> Result + pub fn get_with_generics<'a, T, Args, Rets>( + &'a self, + ctx: &impl AsContextRef, + name: &str, + ) -> Result where Args: WasmTypeList, Rets: WasmTypeList, @@ -173,19 +179,23 @@ impl Exports { { match self.map.get(name) { None => Err(ExportError::Missing(name.to_string())), - Some(extern_) => T::get_self_from_extern_with_generics(extern_), + Some(extern_) => T::get_self_from_extern_with_generics(ctx, extern_), } } /// Like `get_with_generics` but with a WeakReference to the `InstanceRef` internally. - /// This is useful for passing data into `WasmerEnv`, for example. - pub fn get_with_generics_weak<'a, T, Args, Rets>(&'a self, name: &str) -> Result + /// This is useful for passing data into Context data, for example. + pub fn get_with_generics_weak<'a, T, Args, Rets>( + &'a self, + ctx: &impl AsContextRef, + name: &str, + ) -> Result where Args: WasmTypeList, Rets: WasmTypeList, T: ExportableWithGenerics<'a, Args, Rets>, { - let out: T = self.get_with_generics(name)?; + let out: T = self.get_with_generics(ctx, name)?; Ok(out) } @@ -311,12 +321,6 @@ impl<'a> IntoIterator for &'a Exports { /// /// [`Instance`]: crate::js::Instance pub trait Exportable<'a>: Sized { - /// This function is used when providedd the [`Extern`] as exportable, so it - /// can be used while instantiating the [`Module`]. - /// - /// [`Module`]: crate::js::Module - fn to_export(&self) -> Export; - /// Implementation of how to get the export corresponding to the implementing type /// from an [`Instance`] by name. /// @@ -329,13 +333,19 @@ pub trait Exportable<'a>: Sized { /// as well. pub trait ExportableWithGenerics<'a, Args: WasmTypeList, Rets: WasmTypeList>: Sized { /// Get an export with the given generics. - fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result; + fn get_self_from_extern_with_generics( + ctx: &impl AsContextRef, + _extern: &'a Extern, + ) -> Result; } /// We implement it for all concrete [`Exportable`] types (that are `Clone`) /// with empty `Args` and `Rets`. impl<'a, T: Exportable<'a> + Clone + 'static> ExportableWithGenerics<'a, (), ()> for T { - fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result { + fn get_self_from_extern_with_generics( + _ctx: &impl AsContextRef, + _extern: &'a Extern, + ) -> Result { T::get_self_from_extern(_extern).map(|i| i.clone()) } } diff --git a/lib/api/src/js/externals/function.rs b/lib/api/src/js/externals/function.rs index 58981dcf150..17d6cd56b7a 100644 --- a/lib/api/src/js/externals/function.rs +++ b/lib/api/src/js/externals/function.rs @@ -1,30 +1,32 @@ +pub use self::inner::{FromToNativeWasmType, HostFunction, WasmTypeList}; +use crate::js::context::{ + AsContextMut, AsContextRef, ContextHandle, ContextMut, InternalContextHandle, +}; use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; -use crate::js::store::Store; -use crate::js::types::{param_from_js, AsJs /* ValFuncRef */, Val}; +use crate::js::types::{param_from_js, AsJs}; /* ValFuncRef */ use crate::js::FunctionType; use crate::js::RuntimeError; use crate::js::TypedFunction; -use crate::js::WasmerEnv; -pub use inner::{FromToNativeWasmType, HostFunction, WasmTypeList, WithEnv, WithoutEnv}; +use crate::js::Value; use js_sys::{Array, Function as JSFunction}; use std::iter::FromIterator; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; -use crate::js::export::{Export, VMFunction}; +use crate::js::export::VMFunction; use std::fmt; #[repr(C)] pub struct VMFunctionBody(u8); #[inline] -fn result_to_js(val: &Val) -> JsValue { +fn result_to_js(val: &Value) -> JsValue { match val { - Val::I32(i) => JsValue::from_f64(*i as _), - Val::I64(i) => JsValue::from_f64(*i as _), - Val::F32(f) => JsValue::from_f64(*f as _), - Val::F64(f) => JsValue::from_f64(*f), + Value::I32(i) => JsValue::from_f64(*i as _), + Value::I64(i) => JsValue::from_f64(*i as _), + Value::F32(f) => JsValue::from_f64(*f as _), + Value::F64(f) => JsValue::from_f64(*f), val => unimplemented!( "The value `{:?}` is not yet supported in the JS Function API", val @@ -33,7 +35,7 @@ fn result_to_js(val: &Val) -> JsValue { } #[inline] -fn results_to_js_array(values: &[Val]) -> Array { +fn results_to_js_array(values: &[Value]) -> Array { Array::from_iter(values.iter().map(result_to_js)) } @@ -56,12 +58,9 @@ fn results_to_js_array(values: &[Val]) -> Array { /// [Closures as host functions tracking issue](https://github.com/wasmerio/wasmer/issues/1840) #[derive(Clone, PartialEq)] pub struct Function { - pub(crate) store: Store, - pub(crate) exported: VMFunction, + pub(crate) handle: ContextHandle, } -impl WasmerEnv for WithoutEnv {} - impl Function { /// Creates a new host `Function` (dynamic) with the provided signature. /// @@ -96,47 +95,55 @@ impl Function { /// }); /// ``` #[allow(clippy::cast_ptr_alignment)] - pub fn new(store: &Store, ty: FT, func: F) -> Self + pub fn new(ctx: &mut impl AsContextMut, ty: FT, func: F) -> Self where FT: Into, - F: Fn(&[Val]) -> Result, RuntimeError> + 'static + Send + Sync, + F: Fn(ContextMut<'_, T>, &[Value]) -> Result, RuntimeError> + + 'static + + Send + + Sync, { - let ty = ty.into(); - let new_ty = ty.clone(); + let mut ctx = ctx.as_context_mut(); + let function_type = ty.into(); + let func_ty = function_type.clone(); + let raw_ctx = ctx.as_raw() as *mut u8; - let wrapped_func: JsValue = match ty.results().len() { + let wrapped_func: JsValue = match function_type.results().len() { 0 => Closure::wrap(Box::new(move |args: &Array| { - let wasm_arguments = new_ty + let mut ctx: ContextMut = unsafe { ContextMut::from_raw(raw_ctx as _) }; + let wasm_arguments = function_type .params() .iter() .enumerate() .map(|(i, param)| param_from_js(param, &args.get(i as u32))) .collect::>(); - let _results = func(&wasm_arguments)?; + let _results = func(ctx.as_context_mut(), &wasm_arguments)?; Ok(()) }) as Box Result<(), JsValue>>) .into_js_value(), 1 => Closure::wrap(Box::new(move |args: &Array| { - let wasm_arguments = new_ty + let mut ctx: ContextMut = unsafe { ContextMut::from_raw(raw_ctx as _) }; + let wasm_arguments = function_type .params() .iter() .enumerate() .map(|(i, param)| param_from_js(param, &args.get(i as u32))) .collect::>(); - let results = func(&wasm_arguments)?; + let results = func(ctx.as_context_mut(), &wasm_arguments)?; return Ok(result_to_js(&results[0])); }) as Box Result>) .into_js_value(), _n => Closure::wrap(Box::new(move |args: &Array| { - let wasm_arguments = new_ty + let mut ctx: ContextMut = unsafe { ContextMut::from_raw(raw_ctx as _) }; + let wasm_arguments = function_type .params() .iter() .enumerate() .map(|(i, param)| param_from_js(param, &args.get(i as u32))) .collect::>(); - let results = func(&wasm_arguments)?; + let results = func(ctx.as_context_mut(), &wasm_arguments)?; return Ok(results_to_js_array(&results)); }) as Box Result>) @@ -146,124 +153,8 @@ impl Function { let dyn_func = JSFunction::new_with_args("f", "return f(Array.prototype.slice.call(arguments, 1))"); let binded_func = dyn_func.bind1(&JsValue::UNDEFINED, &wrapped_func); - Self { - store: store.clone(), - exported: VMFunction::new(binded_func, ty, None), - } - } - - /// Creates a new host `Function` (dynamic) with the provided signature and environment. - /// - /// If you know the signature of the host function at compile time, - /// consider using [`Function::new_native_with_env`] for less runtime - /// overhead. - /// - /// # Examples - /// - /// ``` - /// # use wasmer::{Function, FunctionType, Type, Store, Value, WasmerEnv}; - /// # let store = Store::default(); - /// # - /// #[derive(WasmerEnv, Clone)] - /// struct Env { - /// multiplier: i32, - /// }; - /// let env = Env { multiplier: 2 }; - /// - /// let signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]); - /// - /// let f = Function::new_with_env(&store, &signature, env, |env, args| { - /// let result = env.multiplier * (args[0].unwrap_i32() + args[1].unwrap_i32()); - /// Ok(vec![Value::I32(result)]) - /// }); - /// ``` - /// - /// With constant signature: - /// - /// ``` - /// # use wasmer::{Function, FunctionType, Type, Store, Value, WasmerEnv}; - /// # let store = Store::default(); - /// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]); - /// - /// #[derive(WasmerEnv, Clone)] - /// struct Env { - /// multiplier: i32, - /// }; - /// let env = Env { multiplier: 2 }; - /// - /// let f = Function::new_with_env(&store, I32_I32_TO_I32, env, |env, args| { - /// let result = env.multiplier * (args[0].unwrap_i32() + args[1].unwrap_i32()); - /// Ok(vec![Value::I32(result)]) - /// }); - /// ``` - #[allow(clippy::cast_ptr_alignment)] - pub fn new_with_env(store: &Store, ty: FT, env: Env, func: F) -> Self - where - FT: Into, - F: Fn(&Env, &[Val]) -> Result, RuntimeError> + 'static + Send + Sync, - Env: Sized + WasmerEnv + 'static, - { - let ty = ty.into(); - let new_ty = ty.clone(); - - let wrapped_func: JsValue = match ty.results().len() { - 0 => Closure::wrap(Box::new(move |args: &Array| { - let wasm_arguments = new_ty - .params() - .iter() - .enumerate() - .map(|(i, param)| param_from_js(param, &args.get(i as u32 + 1))) - .collect::>(); - let env_ptr = args.get(0).as_f64().unwrap() as usize; - let env: &Env = unsafe { &*(env_ptr as *const u8 as *const Env) }; - let _results = func(env, &wasm_arguments)?; - Ok(()) - }) - as Box Result<(), JsValue>>) - .into_js_value(), - 1 => Closure::wrap(Box::new(move |args: &Array| { - let wasm_arguments = new_ty - .params() - .iter() - .enumerate() - .map(|(i, param)| param_from_js(param, &args.get(i as u32 + 1))) - .collect::>(); - let env_ptr = args.get(0).as_f64().unwrap() as usize; - let env: &Env = unsafe { &*(env_ptr as *const u8 as *const Env) }; - let results = func(env, &wasm_arguments)?; - return Ok(result_to_js(&results[0])); - }) - as Box Result>) - .into_js_value(), - _n => Closure::wrap(Box::new(move |args: &Array| { - let wasm_arguments = new_ty - .params() - .iter() - .enumerate() - .map(|(i, param)| param_from_js(param, &args.get(i as u32 + 1))) - .collect::>(); - let env_ptr = args.get(0).as_f64().unwrap() as usize; - let env: &Env = unsafe { &*(env_ptr as *const u8 as *const Env) }; - let results = func(env, &wasm_arguments)?; - return Ok(results_to_js_array(&results)); - }) - as Box Result>) - .into_js_value(), - }; - - let dyn_func = - JSFunction::new_with_args("f", "return f(Array.prototype.slice.call(arguments, 1))"); - - let environment = Box::new(env); - let binded_func = dyn_func.bind2( - &JsValue::UNDEFINED, - &wrapped_func, - &JsValue::from_f64(&*environment as *const Env as *const u8 as usize as f64), - ); - Self { - store: store.clone(), - exported: VMFunction::new(binded_func, ty, Some(environment)), - } + let vm_function = VMFunction::new(binded_func, func_ty); + Self::from_vm_export(&mut ctx, vm_function) } /// Creates a new host `Function` from a native function. @@ -283,13 +174,13 @@ impl Function { /// /// let f = Function::new_native(&store, sum); /// ``` - pub fn new_native(store: &Store, func: F) -> Self + pub fn new_native(ctx: &mut impl AsContextMut, func: F) -> Self where - F: HostFunction, + F: HostFunction, Args: WasmTypeList, Rets: WasmTypeList, - Env: Sized + 'static, { + let mut ctx = ctx.as_context_mut(); if std::mem::size_of::() != 0 { Self::closures_unsupported_panic(); } @@ -299,63 +190,15 @@ impl Function { let ft = wasm_bindgen::function_table(); let as_table = ft.unchecked_ref::(); let func = as_table.get(address).unwrap(); - let binded_func = func.bind1(&JsValue::UNDEFINED, &JsValue::UNDEFINED); - let ty = function.ty(); - Self { - store: store.clone(), - exported: VMFunction::new(binded_func, ty, None), - } - } - - /// Creates a new host `Function` from a native function and a provided environment. - /// - /// The function signature is automatically retrieved using the - /// Rust typing system. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Store, Function, WasmerEnv}; - /// # let store = Store::default(); - /// # - /// #[derive(WasmerEnv, Clone)] - /// struct Env { - /// multiplier: i32, - /// }; - /// let env = Env { multiplier: 2 }; - /// - /// fn sum_and_multiply(env: &Env, a: i32, b: i32) -> i32 { - /// (a + b) * env.multiplier - /// } - /// - /// let f = Function::new_native_with_env(&store, env, sum_and_multiply); - /// ``` - pub fn new_native_with_env(store: &Store, env: Env, func: F) -> Self - where - F: HostFunction, - Args: WasmTypeList, - Rets: WasmTypeList, - Env: Sized + WasmerEnv + 'static, - { - if std::mem::size_of::() != 0 { - Self::closures_unsupported_panic(); - } - let function = inner::Function::::new(func); - let address = function.address() as usize as u32; - let ft = wasm_bindgen::function_table(); - let as_table = ft.unchecked_ref::(); - let func = as_table.get(address).unwrap(); - let ty = function.ty(); - let environment = Box::new(env); let binded_func = func.bind1( &JsValue::UNDEFINED, - &JsValue::from_f64(&*environment as *const Env as *const u8 as usize as f64), + &JsValue::from_f64(ctx.as_raw() as *mut u8 as usize as f64), ); - // panic!("Function env {:?}", environment.type_id()); + let ty = function.ty(); + let vm_function = VMFunction::new(binded_func, ty); Self { - store: store.clone(), - exported: VMFunction::new(binded_func, ty, Some(environment)), + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), } } @@ -376,13 +219,8 @@ impl Function { /// assert_eq!(f.ty().params(), vec![Type::I32, Type::I32]); /// assert_eq!(f.ty().results(), vec![Type::I32]); /// ``` - pub fn ty(&self) -> &FunctionType { - &self.exported.ty - } - - /// Returns the [`Store`] where the `Function` belongs. - pub fn store(&self) -> &Store { - &self.store + pub fn ty<'context>(&self, ctx: &'context impl AsContextRef) -> &'context FunctionType { + &self.handle.get(ctx.as_context_ref().objects()).ty } /// Returns the number of parameters that this function takes. @@ -401,8 +239,8 @@ impl Function { /// /// assert_eq!(f.param_arity(), 2); /// ``` - pub fn param_arity(&self) -> usize { - self.ty().params().len() + pub fn param_arity(&self, ctx: &impl AsContextRef) -> usize { + self.ty(ctx).params().len() } /// Returns the number of results this function produces. @@ -421,8 +259,8 @@ impl Function { /// /// assert_eq!(f.result_arity(), 1); /// ``` - pub fn result_arity(&self) -> usize { - self.ty().results().len() + pub fn result_arity(&self, ctx: &impl AsContextRef) -> usize { + self.ty(ctx).results().len() } /// Call the `Function` function. @@ -454,16 +292,27 @@ impl Function { /// /// assert_eq!(sum.call(&[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); /// ``` - pub fn call(&self, params: &[Val]) -> Result, RuntimeError> { + pub fn call( + &self, + ctx: &mut impl AsContextMut, + params: &[Value], + ) -> Result, RuntimeError> { let arr = js_sys::Array::new_with_length(params.len() as u32); + + // let raw_ctx = ctx.as_context_mut().as_raw() as *mut u8; + // let mut ctx = unsafe { ContextMut::from_raw(raw_ctx as *mut ContextInner<()>) }; + for (i, param) in params.iter().enumerate() { - let js_value = param.as_jsvalue(); + let js_value = param.as_jsvalue(&ctx.as_context_ref()); arr.set(i as u32, js_value); } - let result = - js_sys::Reflect::apply(&self.exported.function, &wasm_bindgen::JsValue::NULL, &arr)?; + let result = js_sys::Reflect::apply( + &self.handle.get(ctx.as_context_ref().objects()).function, + &wasm_bindgen::JsValue::NULL, + &arr, + )?; - let result_types = self.exported.ty.results(); + let result_types = self.handle.get(ctx.as_context_ref().objects()).ty.results(); match result_types.len() { 0 => Ok(Box::new([])), 1 => { @@ -482,10 +331,20 @@ impl Function { } } - pub(crate) fn from_vm_export(store: &Store, wasmer_export: VMFunction) -> Self { + pub(crate) fn from_vm_export(ctx: &mut impl AsContextMut, vm_function: VMFunction) -> Self { Self { - store: store.clone(), - exported: wasmer_export, + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), + } + } + + pub(crate) fn from_vm_extern( + ctx: &mut impl AsContextMut, + internal: InternalContextHandle, + ) -> Self { + Self { + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, } } @@ -564,14 +423,19 @@ impl Function { /// // This results in an error: `RuntimeError` /// let sum_native = sum.native::<(i32, i32), i64>().unwrap(); /// ``` - pub fn native(&self) -> Result, RuntimeError> + pub fn native( + &self, + ctx: &impl AsContextRef, + ) -> Result, RuntimeError> where Args: WasmTypeList, Rets: WasmTypeList, { + let vm_function = self.handle.get(ctx.as_context_ref().objects()); + // type check { - let expected = self.exported.ty.params(); + let expected = vm_function.ty.params(); let given = Args::wasm_types(); if expected != given { @@ -584,7 +448,7 @@ impl Function { } { - let expected = self.exported.ty.results(); + let expected = vm_function.ty.results(); let given = Rets::wasm_types(); if expected != given { @@ -597,23 +461,21 @@ impl Function { } } - Ok(TypedFunction::new( - self.store.clone(), - self.exported.clone(), - )) + Ok(TypedFunction::from_handle(self.clone())) } #[track_caller] fn closures_unsupported_panic() -> ! { unimplemented!("Closures (functions with captured environments) are currently unsupported with native functions. See: https://github.com/wasmerio/wasmer/issues/1840") } -} -impl<'a> Exportable<'a> for Function { - fn to_export(&self) -> Export { - Export::Function(self.exported.clone()) + /// Checks whether this `Function` can be used with the given context. + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } +} +impl<'a> Exportable<'a> for Function { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Function(func) => Ok(func), @@ -624,10 +486,7 @@ impl<'a> Exportable<'a> for Function { impl fmt::Debug for Function { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter - .debug_struct("Function") - .field("ty", &self.ty()) - .finish() + formatter.debug_struct("Function").finish() } } @@ -636,6 +495,8 @@ impl fmt::Debug for Function { mod inner { use super::RuntimeError; use super::VMFunctionBody; + use crate::js::context::{AsContextMut, ContextInner, ContextMut}; + use crate::js::NativeWasmTypeInto; use std::array::TryFromSliceError; use std::convert::{Infallible, TryInto}; use std::error::Error; @@ -657,7 +518,7 @@ mod inner { Self: Sized, { /// Native Wasm type. - type Native: NativeWasmType; + type Native: NativeWasmTypeInto; /// Convert a value of kind `Self::Native` to `Self`. /// @@ -736,7 +597,7 @@ mod inner { #[cfg(test)] mod test_from_to_native_wasm_type { - use super::*; + use super::FromToNativeWasmType; #[test] fn test_to_native() { @@ -772,13 +633,15 @@ mod inner { /// The array type that can hold all the represented values. /// /// Note that all values are stored in their binary form. - type Array: AsMut<[i128]>; + type Array: AsMut<[f64]>; /// The size of the array fn size() -> u32; /// Constructs `Self` based on an array of values. - fn from_array(array: Self::Array) -> Self; + /// + /// # Safety + unsafe fn from_array(ctx: &mut impl AsContextMut, array: Self::Array) -> Self; /// Constructs `Self` based on a slice of values. /// @@ -786,11 +649,18 @@ mod inner { /// that the slice doesn't have the same size than /// `Self::Array`, in which circumstance an error of kind /// `TryFromSliceError` will be returned. - fn from_slice(slice: &[i128]) -> Result; + /// + /// # Safety + unsafe fn from_slice( + ctx: &mut impl AsContextMut, + slice: &[f64], + ) -> Result; /// Builds and returns an array of type `Array` from a tuple /// (list) of values. - fn into_array(self) -> Self::Array; + /// + /// # Safety + unsafe fn into_array(self, ctx: &mut impl AsContextMut) -> Self::Array; /// Allocates and return an empty array of type `Array` that /// will hold a tuple (list) of values, usually to hold the @@ -799,11 +669,20 @@ mod inner { /// Builds a tuple (list) of values from a C struct of type /// `CStruct`. - fn from_c_struct(c_struct: Self::CStruct) -> Self; + /// + /// # Safety + unsafe fn from_c_struct(ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self; /// Builds and returns a C struct of type `CStruct` from a /// tuple (list) of values. - fn into_c_struct(self) -> Self::CStruct; + /// + /// # Safety + unsafe fn into_c_struct(self, ctx: &mut impl AsContextMut) -> Self::CStruct; + + /// Writes the contents of a C struct to an array of `f64`. + /// + /// # Safety + unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, ptr: *mut f64); /// Get the Wasm types for the tuple (list) of currently /// represented values. @@ -899,11 +778,10 @@ mod inner { /// can be used as host function. To uphold this statement, it is /// necessary for a function to be transformed into a pointer to /// `VMFunctionBody`. - pub trait HostFunction + pub trait HostFunction where Args: WasmTypeList, Rets: WasmTypeList, - Kind: HostFunctionKind, T: Sized, Self: Sized, { @@ -911,28 +789,6 @@ mod inner { fn function_body_ptr(self) -> *const VMFunctionBody; } - /// Empty trait to specify the kind of `HostFunction`: With or - /// without an environment. - /// - /// This trait is never aimed to be used by a user. It is used by - /// the trait system to automatically generate the appropriate - /// host functions. - #[doc(hidden)] - pub trait HostFunctionKind {} - - /// An empty struct to help Rust typing to determine - /// when a `HostFunction` does have an environment. - pub struct WithEnv; - - impl HostFunctionKind for WithEnv {} - - /// An empty struct to help Rust typing to determine - /// when a `HostFunction` does not have an environment. - #[derive(Clone)] - pub struct WithoutEnv; - - impl HostFunctionKind for WithoutEnv {} - /// Represents a low-level Wasm static host function. See /// `super::Function::new` and `super::Function::new_env` to learn /// more. @@ -950,11 +806,11 @@ mod inner { Rets: WasmTypeList, { /// Creates a new `Function`. - pub fn new(function: F) -> Self + #[allow(dead_code)] + pub fn new(function: F) -> Self where - F: HostFunction, - T: HostFunctionKind, - E: Sized, + F: HostFunction, + T: Sized, { Self { address: function.function_body_ptr(), @@ -963,11 +819,13 @@ mod inner { } /// Get the function type of this `Function`. + #[allow(dead_code)] pub fn ty(&self) -> FunctionType { FunctionType::new(Args::wasm_types(), Rets::wasm_types()) } /// Get the address of this `Function`. + #[allow(dead_code)] pub fn address(&self) -> *const VMFunctionBody { self.address } @@ -981,7 +839,7 @@ mod inner { /// A structure with a C-compatible representation that can hold a set of Wasm values. /// This type is used by `WasmTypeList::CStruct`. #[repr($c_struct_representation)] - pub struct $c_struct_name< $( $x ),* > ( $( <$x as FromToNativeWasmType>::Native ),* ) + pub struct $c_struct_name< $( $x ),* > ( $( <<$x as FromToNativeWasmType>::Native as NativeWasmType>::Abi ),* ) where $( $x: FromToNativeWasmType ),*; @@ -996,13 +854,16 @@ mod inner { { type CStruct = $c_struct_name< $( $x ),* >; - type Array = [i128; count_idents!( $( $x ),* )]; + type Array = [f64; count_idents!( $( $x ),* )]; fn size() -> u32 { count_idents!( $( $x ),* ) as _ } - fn from_array(array: Self::Array) -> Self { + #[allow(unused_mut)] + #[allow(clippy::unused_unit)] + #[allow(clippy::missing_safety_doc)] + unsafe fn from_array(mut _ctx: &mut impl AsContextMut, array: Self::Array) -> Self { // Unpack items of the array. #[allow(non_snake_case)] let [ $( $x ),* ] = array; @@ -1010,16 +871,19 @@ mod inner { // Build the tuple. ( $( - FromToNativeWasmType::from_native(NativeWasmType::from_binary($x)) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_ctx, $x)) ),* ) } - fn from_slice(slice: &[i128]) -> Result { - Ok(Self::from_array(slice.try_into()?)) + #[allow(clippy::missing_safety_doc)] + unsafe fn from_slice(ctx: &mut impl AsContextMut, slice: &[f64]) -> Result { + Ok(Self::from_array(ctx, slice.try_into()?)) } - fn into_array(self) -> Self::Array { + #[allow(unused_mut)] + #[allow(clippy::missing_safety_doc)] + unsafe fn into_array(self, mut _ctx: &mut impl AsContextMut) -> Self::Array { // Unpack items of the tuple. #[allow(non_snake_case)] let ( $( $x ),* ) = self; @@ -1027,41 +891,57 @@ mod inner { // Build the array. [ $( - FromToNativeWasmType::to_native($x).to_binary() + FromToNativeWasmType::to_native($x).into_raw(_ctx) ),* ] } fn empty_array() -> Self::Array { // Build an array initialized with `0`. - [0; count_idents!( $( $x ),* )] + [0_f64; count_idents!( $( $x ),* )] } - fn from_c_struct(c_struct: Self::CStruct) -> Self { + #[allow(unused_mut)] + #[allow(clippy::unused_unit)] + #[allow(clippy::missing_safety_doc)] + unsafe fn from_c_struct(mut _ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self { // Unpack items of the C structure. #[allow(non_snake_case)] let $c_struct_name( $( $x ),* ) = c_struct; ( $( - FromToNativeWasmType::from_native($x) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_ctx, $x)) ),* ) } - #[allow(unused_parens, non_snake_case)] - fn into_c_struct(self) -> Self::CStruct { + #[allow(unused_parens, non_snake_case, unused_mut)] + #[allow(clippy::missing_safety_doc)] + unsafe fn into_c_struct(self, mut _ctx: &mut impl AsContextMut) -> Self::CStruct { // Unpack items of the tuple. let ( $( $x ),* ) = self; // Build the C structure. $c_struct_name( $( - FromToNativeWasmType::to_native($x) + FromToNativeWasmType::to_native($x).into_abi(_ctx) ),* ) } + #[allow(non_snake_case)] + unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, _ptr: *mut f64) { + // Unpack items of the tuple. + let $c_struct_name( $( $x ),* ) = c_struct; + + let mut _n = 0; + $( + *_ptr.add(_n).cast() = $x; + _n += 1; + )* + } + fn wasm_types() -> &'static [Type] { &[ $( @@ -1072,90 +952,46 @@ mod inner { } // Implement `HostFunction` for a function that has the same arity than the tuple. - // This specific function has no environment. - #[allow(unused_parens)] - impl< $( $x, )* Rets, RetsAsResult, Func > - HostFunction<( $( $x ),* ), Rets, WithoutEnv, ()> - for - Func - where - $( $x: FromToNativeWasmType, )* - Rets: WasmTypeList, - RetsAsResult: IntoResult, - Func: Fn($( $x , )*) -> RetsAsResult + 'static + Send, - { - #[allow(non_snake_case)] - fn function_body_ptr(self) -> *const VMFunctionBody { - /// This is a function that wraps the real host - /// function. Its address will be used inside the - /// runtime. - extern fn func_wrapper<$( $x, )* Rets, RetsAsResult, Func>( _: usize, $( $x: $x::Native, )* ) -> Rets::CStruct - where - $( $x: FromToNativeWasmType, )* - Rets: WasmTypeList, - RetsAsResult: IntoResult, - Func: Fn( $( $x ),* ) -> RetsAsResult + 'static - { - let func: &Func = unsafe { &*(&() as *const () as *const Func) }; - let result = panic::catch_unwind(AssertUnwindSafe(|| { - func( $( FromToNativeWasmType::from_native($x) ),* ).into_result() - })); - match result { - Ok(Ok(result)) => return result.into_c_struct(), - Ok(Err(trap)) => RuntimeError::raise(Box::new(trap)), - _ => unimplemented!(), - // Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) }, - // Err(panic) => unsafe { resume_panic(panic) }, - } - } - - func_wrapper::< $( $x, )* Rets, RetsAsResult, Self > as *const VMFunctionBody - } - } - - // Implement `HostFunction` for a function that has the same arity than the tuple. - // This specific function has an environment. #[allow(unused_parens)] - impl< $( $x, )* Rets, RetsAsResult, Env, Func > - HostFunction<( $( $x ),* ), Rets, WithEnv, Env> + impl< $( $x, )* Rets, RetsAsResult, T, Func > + HostFunction for Func where $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Env: Sized, - Func: Fn(&Env, $( $x , )*) -> RetsAsResult + Send + 'static, + Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, { #[allow(non_snake_case)] fn function_body_ptr(self) -> *const VMFunctionBody { /// This is a function that wraps the real host /// function. Its address will be used inside the /// runtime. - extern fn func_wrapper<$( $x, )* Rets, RetsAsResult, Env, Func>( ptr: usize, $( $x: $x::Native, )* ) -> Rets::CStruct + unsafe extern "C" fn func_wrapper( ctx_ptr: usize, $( $x: <$x::Native as NativeWasmType>::Abi, )* ) -> Rets::CStruct where $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Env: Sized, - Func: Fn(&Env, $( $x ),* ) -> RetsAsResult + 'static + Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, { - let env: &Env = unsafe { &*(ptr as *const u8 as *const Env) }; - let func: &Func = unsafe { &*(&() as *const () as *const Func) }; + let func: &Func = &*(&() as *const () as *const Func); + let mut ctx = ContextMut::from_raw(ctx_ptr as *mut ContextInner); + let mut ctx2 = ContextMut::from_raw(ctx_ptr as *mut ContextInner); let result = panic::catch_unwind(AssertUnwindSafe(|| { - func(env, $( FromToNativeWasmType::from_native($x) ),* ).into_result() + func(ctx2.as_context_mut(), $( FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(&mut ctx, $x)) ),* ).into_result() })); + match result { - Ok(Ok(result)) => return result.into_c_struct(), + Ok(Ok(result)) => return result.into_c_struct(&mut ctx), + #[allow(deprecated)] Ok(Err(trap)) => RuntimeError::raise(Box::new(trap)), - _ => unimplemented!(), - // Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) }, - // Err(panic) => unsafe { resume_panic(panic) }, + Err(_panic) => unimplemented!(), } } - func_wrapper::< $( $x, )* Rets, RetsAsResult, Env, Self > as *const VMFunctionBody + func_wrapper::< T, $( $x, )* Rets, RetsAsResult, Self > as *const VMFunctionBody } } }; @@ -1209,171 +1045,170 @@ mod inner { // fail (with `Result<_, Infallible>`). impl WasmTypeList for Infallible { type CStruct = Self; - type Array = [i128; 0]; + type Array = [f64; 0]; fn size() -> u32 { 0 } - fn from_array(_: Self::Array) -> Self { + unsafe fn from_array(_: &mut impl AsContextMut, _: Self::Array) -> Self { unreachable!() } - fn from_slice(_: &[i128]) -> Result { + unsafe fn from_slice( + _: &mut impl AsContextMut, + _: &[f64], + ) -> Result { unreachable!() } - fn into_array(self) -> Self::Array { + unsafe fn into_array(self, _: &mut impl AsContextMut) -> Self::Array { [] } fn empty_array() -> Self::Array { - unreachable!() + [] } - fn from_c_struct(_: Self::CStruct) -> Self { - unreachable!() + unsafe fn from_c_struct(_: &mut impl AsContextMut, self_: Self::CStruct) -> Self { + self_ } - fn into_c_struct(self) -> Self::CStruct { - unreachable!() + unsafe fn into_c_struct(self, _: &mut impl AsContextMut) -> Self::CStruct { + self } + unsafe fn write_c_struct_to_ptr(_: Self::CStruct, _: *mut f64) {} + fn wasm_types() -> &'static [Type] { &[] } } - #[cfg(test)] - mod test_wasm_type_list { - use super::*; - use wasmer_types::Type; + /* + #[cfg(test)] + mod test_wasm_type_list { + use super::*; + use wasmer_types::Type; + + fn test_from_array() { + assert_eq!(<()>::from_array([]), ()); + assert_eq!(::from_array([1]), (1i32)); + assert_eq!(<(i32, i64)>::from_array([1, 2]), (1i32, 2i64)); + assert_eq!( + <(i32, i64, f32, f64)>::from_array([ + 1, + 2, + (3.1f32).to_bits().into(), + (4.2f64).to_bits().into() + ]), + (1, 2, 3.1f32, 4.2f64) + ); + } - #[test] - fn test_from_array() { - assert_eq!(<()>::from_array([]), ()); - assert_eq!(::from_array([1]), (1i32)); - assert_eq!(<(i32, i64)>::from_array([1, 2]), (1i32, 2i64)); - assert_eq!( - <(i32, i64, f32, f64)>::from_array([ - 1, - 2, - (3.1f32).to_bits().into(), - (4.2f64).to_bits().into() - ]), - (1, 2, 3.1f32, 4.2f64) - ); - } + fn test_into_array() { + assert_eq!(().into_array(), [0; 0]); + assert_eq!((1).into_array(), [1]); + assert_eq!((1i32, 2i64).into_array(), [1, 2]); + assert_eq!( + (1i32, 2i32, 3.1f32, 4.2f64).into_array(), + [1, 2, (3.1f32).to_bits().into(), (4.2f64).to_bits().into()] + ); + } - #[test] - fn test_into_array() { - assert_eq!(().into_array(), [0i128; 0]); - assert_eq!((1).into_array(), [1]); - assert_eq!((1i32, 2i64).into_array(), [1, 2]); - assert_eq!( - (1i32, 2i32, 3.1f32, 4.2f64).into_array(), - [1, 2, (3.1f32).to_bits().into(), (4.2f64).to_bits().into()] - ); - } + fn test_empty_array() { + assert_eq!(<()>::empty_array().len(), 0); + assert_eq!(::empty_array().len(), 1); + assert_eq!(<(i32, i64)>::empty_array().len(), 2); + } - #[test] - fn test_empty_array() { - assert_eq!(<()>::empty_array().len(), 0); - assert_eq!(::empty_array().len(), 1); - assert_eq!(<(i32, i64)>::empty_array().len(), 2); - } + fn test_from_c_struct() { + assert_eq!(<()>::from_c_struct(S0()), ()); + assert_eq!(::from_c_struct(S1(1)), (1i32)); + assert_eq!(<(i32, i64)>::from_c_struct(S2(1, 2)), (1i32, 2i64)); + assert_eq!( + <(i32, i64, f32, f64)>::from_c_struct(S4(1, 2, 3.1, 4.2)), + (1i32, 2i64, 3.1f32, 4.2f64) + ); + } - #[test] - fn test_from_c_struct() { - assert_eq!(<()>::from_c_struct(S0()), ()); - assert_eq!(::from_c_struct(S1(1)), (1i32)); - assert_eq!(<(i32, i64)>::from_c_struct(S2(1, 2)), (1i32, 2i64)); - assert_eq!( - <(i32, i64, f32, f64)>::from_c_struct(S4(1, 2, 3.1, 4.2)), - (1i32, 2i64, 3.1f32, 4.2f64) - ); - } + fn test_wasm_types_for_uni_values() { + assert_eq!(::wasm_types(), [Type::I32]); + assert_eq!(::wasm_types(), [Type::I64]); + assert_eq!(::wasm_types(), [Type::F32]); + assert_eq!(::wasm_types(), [Type::F64]); + } - #[test] - fn test_wasm_types_for_uni_values() { - assert_eq!(::wasm_types(), [Type::I32]); - assert_eq!(::wasm_types(), [Type::I64]); - assert_eq!(::wasm_types(), [Type::F32]); - assert_eq!(::wasm_types(), [Type::F64]); - } + fn test_wasm_types_for_multi_values() { + assert_eq!(<(i32, i32)>::wasm_types(), [Type::I32, Type::I32]); + assert_eq!(<(i64, i64)>::wasm_types(), [Type::I64, Type::I64]); + assert_eq!(<(f32, f32)>::wasm_types(), [Type::F32, Type::F32]); + assert_eq!(<(f64, f64)>::wasm_types(), [Type::F64, Type::F64]); - #[test] - fn test_wasm_types_for_multi_values() { - assert_eq!(<(i32, i32)>::wasm_types(), [Type::I32, Type::I32]); - assert_eq!(<(i64, i64)>::wasm_types(), [Type::I64, Type::I64]); - assert_eq!(<(f32, f32)>::wasm_types(), [Type::F32, Type::F32]); - assert_eq!(<(f64, f64)>::wasm_types(), [Type::F64, Type::F64]); - - assert_eq!( - <(i32, i64, f32, f64)>::wasm_types(), - [Type::I32, Type::I64, Type::F32, Type::F64] - ); + assert_eq!( + <(i32, i64, f32, f64)>::wasm_types(), + [Type::I32, Type::I64, Type::F32, Type::F64] + ); + } } - } - #[allow(non_snake_case)] - #[cfg(test)] - mod test_function { - use super::*; - use wasmer_types::Type; + #[allow(non_snake_case)] + #[cfg(test)] + mod test_function { + use super::*; + use wasmer_types::Type; - fn func() {} - fn func__i32() -> i32 { - 0 - } - fn func_i32(_a: i32) {} - fn func_i32__i32(a: i32) -> i32 { - a * 2 - } - fn func_i32_i32__i32(a: i32, b: i32) -> i32 { - a + b - } - fn func_i32_i32__i32_i32(a: i32, b: i32) -> (i32, i32) { - (a, b) - } - fn func_f32_i32__i32_f32(a: f32, b: i32) -> (i32, f32) { - (b, a) - } + fn func() {} + fn func__i32() -> i32 { + 0 + } + fn func_i32(_a: i32) {} + fn func_i32__i32(a: i32) -> i32 { + a * 2 + } + fn func_i32_i32__i32(a: i32, b: i32) -> i32 { + a + b + } + fn func_i32_i32__i32_i32(a: i32, b: i32) -> (i32, i32) { + (a, b) + } + fn func_f32_i32__i32_f32(a: f32, b: i32) -> (i32, f32) { + (b, a) + } - #[test] - fn test_function_types() { - assert_eq!(Function::new(func).ty(), FunctionType::new(vec![], vec![])); - assert_eq!( - Function::new(func__i32).ty(), - FunctionType::new(vec![], vec![Type::I32]) - ); - assert_eq!( - Function::new(func_i32).ty(), - FunctionType::new(vec![Type::I32], vec![]) - ); - assert_eq!( - Function::new(func_i32__i32).ty(), - FunctionType::new(vec![Type::I32], vec![Type::I32]) - ); - assert_eq!( - Function::new(func_i32_i32__i32).ty(), - FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]) - ); - assert_eq!( - Function::new(func_i32_i32__i32_i32).ty(), - FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]) - ); - assert_eq!( - Function::new(func_f32_i32__i32_f32).ty(), - FunctionType::new(vec![Type::F32, Type::I32], vec![Type::I32, Type::F32]) - ); - } + fn test_function_types() { + assert_eq!(Function::new(func).ty(), FunctionType::new(vec![], vec![])); + assert_eq!( + Function::new(func__i32).ty(), + FunctionType::new(vec![], vec![Type::I32]) + ); + assert_eq!( + Function::new(func_i32).ty(), + FunctionType::new(vec![Type::I32], vec![]) + ); + assert_eq!( + Function::new(func_i32__i32).ty(), + FunctionType::new(vec![Type::I32], vec![Type::I32]) + ); + assert_eq!( + Function::new(func_i32_i32__i32).ty(), + FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]) + ); + assert_eq!( + Function::new(func_i32_i32__i32_i32).ty(), + FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]) + ); + assert_eq!( + Function::new(func_f32_i32__i32_f32).ty(), + FunctionType::new(vec![Type::F32, Type::I32], vec![Type::I32, Type::F32]) + ); + } - #[test] - fn test_function_pointer() { - let f = Function::new(func_i32__i32); - let function = unsafe { std::mem::transmute::<_, fn(usize, i32) -> i32>(f.address) }; - assert_eq!(function(0, 3), 6); + fn test_function_pointer() { + let f = Function::new(func_i32__i32); + let function = unsafe { std::mem::transmute::<_, fn(usize, i32) -> i32>(f.address) }; + assert_eq!(function(0, 3), 6); + } } - } + */ } diff --git a/lib/api/src/js/externals/global.rs b/lib/api/src/js/externals/global.rs index 431547129a2..c570c7b27d9 100644 --- a/lib/api/src/js/externals/global.rs +++ b/lib/api/src/js/externals/global.rs @@ -1,9 +1,8 @@ -use crate::js::export::Export; +use crate::js::context::{AsContextMut, AsContextRef, ContextHandle, InternalContextHandle}; use crate::js::export::VMGlobal; use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; -use crate::js::store::Store; -use crate::js::types::{Val, ValType}; +use crate::js::value::Value; use crate::js::wasm_bindgen_polyfill::Global as JSGlobal; use crate::js::GlobalType; use crate::js::Mutability; @@ -18,12 +17,11 @@ use wasm_bindgen::JsValue; /// Spec: #[derive(Debug, Clone, PartialEq)] pub struct Global { - store: Store, - vm_global: VMGlobal, + pub(crate) handle: ContextHandle, } impl Global { - /// Create a new `Global` with the initial value [`Val`]. + /// Create a new `Global` with the initial value [`Value`]. /// /// # Example /// @@ -36,11 +34,11 @@ impl Global { /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Const); /// ``` - pub fn new(store: &Store, val: Val) -> Self { - Self::from_value(store, val, Mutability::Const).unwrap() + pub fn new(ctx: &mut impl AsContextMut, val: Value) -> Self { + Self::from_value(ctx, val, Mutability::Const).unwrap() } - /// Create a mutable `Global` with the initial value [`Val`]. + /// Create a mutable `Global` with the initial value [`Value`]. /// /// # Example /// @@ -53,22 +51,31 @@ impl Global { /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Var); /// ``` - pub fn new_mut(store: &Store, val: Val) -> Self { - Self::from_value(store, val, Mutability::Var).unwrap() + pub fn new_mut(ctx: &mut impl AsContextMut, val: Value) -> Self { + Self::from_value(ctx, val, Mutability::Var).unwrap() } - /// Create a `Global` with the initial value [`Val`] and the provided [`Mutability`]. - fn from_value(store: &Store, val: Val, mutability: Mutability) -> Result { + /// Create a `Global` with the initial value [`Value`] and the provided [`Mutability`]. + fn from_value( + ctx: &mut impl AsContextMut, + val: Value, + mutability: Mutability, + ) -> Result { + if !val.is_from_context(ctx) { + return Err(RuntimeError::new( + "cross-`Context` values are not supported", + )); + } let global_ty = GlobalType { mutability, ty: val.ty(), }; let descriptor = js_sys::Object::new(); let (type_str, value) = match val { - Val::I32(i) => ("i32", JsValue::from_f64(i as _)), - Val::I64(i) => ("i64", JsValue::from_f64(i as _)), - Val::F32(f) => ("f32", JsValue::from_f64(f as _)), - Val::F64(f) => ("f64", JsValue::from_f64(f)), + Value::I32(i) => ("i32", JsValue::from_f64(i as _)), + Value::I64(i) => ("i64", JsValue::from_f64(i as _)), + Value::F32(f) => ("f32", JsValue::from_f64(f as _)), + Value::F64(f) => ("f64", JsValue::from_f64(f)), _ => unimplemented!("The type is not yet supported in the JS Global API"), }; // This is the value type as string, even though is incorrectly called "value" @@ -81,12 +88,9 @@ impl Global { )?; let js_global = JSGlobal::new(&descriptor, &value).unwrap(); - let global = VMGlobal::new(js_global, global_ty); + let vm_global = VMGlobal::new(js_global, global_ty); - Ok(Self { - store: store.clone(), - vm_global: global, - }) + Ok(Self::from_vm_export(ctx, vm_global)) } /// Returns the [`GlobalType`] of the `Global`. @@ -103,27 +107,11 @@ impl Global { /// assert_eq!(c.ty(), &GlobalType::new(Type::I32, Mutability::Const)); /// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var)); /// ``` - pub fn ty(&self) -> &GlobalType { - &self.vm_global.ty - } - - /// Returns the [`Store`] where the `Global` belongs. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); - /// # - /// let g = Global::new(&store, Value::I32(1)); - /// - /// assert_eq!(g.store(), &store); - /// ``` - pub fn store(&self) -> &Store { - &self.store + pub fn ty(&self, ctx: &impl AsContextRef) -> GlobalType { + self.handle.get(ctx.as_context_ref().objects()).ty } - /// Retrieves the current value [`Val`] that the Global has. + /// Retrieves the current value [`Value`] that the Global has. /// /// # Example /// @@ -135,17 +123,30 @@ impl Global { /// /// assert_eq!(g.get(), Value::I32(1)); /// ``` - pub fn get(&self) -> Val { + pub fn get(&self, ctx: &impl AsContextRef) -> Value { + unsafe { + let raw = self + .handle + .get(ctx.as_context_ref().objects()) + .global + .value() + .as_f64() + .unwrap(); + let ty = self.handle.get(ctx.as_context_ref().objects()).ty; + Value::from_raw(ctx, ty.ty, raw) + } + /* match self.vm_global.ty.ty { - ValType::I32 => Val::I32(self.vm_global.global.value().as_f64().unwrap() as _), - ValType::I64 => Val::I64(self.vm_global.global.value().as_f64().unwrap() as _), - ValType::F32 => Val::F32(self.vm_global.global.value().as_f64().unwrap() as _), - ValType::F64 => Val::F64(self.vm_global.global.value().as_f64().unwrap()), + ValType::I32 => Value::I32(self.vm_global.global.value().as_f64().unwrap() as _), + ValType::I64 => Value::I64(self.vm_global.global.value().as_f64().unwrap() as _), + ValType::F32 => Value::F32(self.vm_global.global.value().as_f64().unwrap() as _), + ValType::F64 => Value::F64(self.vm_global.global.value().as_f64().unwrap()), _ => unimplemented!("The type is not yet supported in the JS Global API"), } + */ } - /// Sets a custom value [`Val`] to the runtime Global. + /// Sets a custom value [`Value`] to the runtime Global. /// /// # Example /// @@ -186,53 +187,61 @@ impl Global { /// // This results in an error: `RuntimeError`. /// g.set(Value::I64(2)).unwrap(); /// ``` - pub fn set(&self, val: Val) -> Result<(), RuntimeError> { - if self.vm_global.ty.mutability == Mutability::Const { + pub fn set(&self, ctx: &mut impl AsContextMut, val: Value) -> Result<(), RuntimeError> { + if !val.is_from_context(ctx) { + return Err(RuntimeError::new( + "cross-`Context` values are not supported", + )); + } + let global_ty = self.ty(&ctx); + if global_ty.mutability == Mutability::Const { return Err(RuntimeError::new("The global is immutable".to_owned())); } - if val.ty() != self.vm_global.ty.ty { + if val.ty() != global_ty.ty { return Err(RuntimeError::new("The types don't match".to_owned())); } let new_value = match val { - Val::I32(i) => JsValue::from_f64(i as _), - Val::I64(i) => JsValue::from_f64(i as _), - Val::F32(f) => JsValue::from_f64(f as _), - Val::F64(f) => JsValue::from_f64(f), - _ => unimplemented!("The type is not yet supported in the JS Global API"), + Value::I32(i) => JsValue::from_f64(i as _), + Value::I64(i) => JsValue::from_f64(i as _), + Value::F32(f) => JsValue::from_f64(f as _), + Value::F64(f) => JsValue::from_f64(f), + _ => { + return Err(RuntimeError::new( + "The type is not yet supported in the JS Global API".to_owned(), + )) + } }; - self.vm_global.global.set_value(&new_value); + self.handle + .get_mut(ctx.as_context_mut().objects_mut()) + .global + .set_value(&new_value); Ok(()) } - pub(crate) fn from_vm_export(store: &Store, vm_global: VMGlobal) -> Self { + pub(crate) fn from_vm_export(ctx: &mut impl AsContextMut, vm_global: VMGlobal) -> Self { Self { - store: store.clone(), - vm_global, + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_global), } } - /// Returns whether or not these two globals refer to the same data. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); - /// # - /// let g = Global::new(&store, Value::I32(1)); - /// - /// assert!(g.same(&g)); - /// ``` - pub fn same(&self, other: &Self) -> bool { - self.vm_global == other.vm_global + pub(crate) fn from_vm_extern( + ctx: &mut impl AsContextMut, + internal: InternalContextHandle, + ) -> Self { + Self { + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, + } } -} -impl<'a> Exportable<'a> for Global { - fn to_export(&self) -> Export { - Export::Global(self.vm_global.clone()) + /// Checks whether this `Global` can be used with the given context. + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } +} +impl<'a> Exportable<'a> for Global { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Global(global) => Ok(global), diff --git a/lib/api/src/js/externals/memory.rs b/lib/api/src/js/externals/memory.rs index 2de3d044db4..d100208c715 100644 --- a/lib/api/src/js/externals/memory.rs +++ b/lib/api/src/js/externals/memory.rs @@ -1,9 +1,12 @@ -use crate::js::export::{Export, VMMemory}; +use crate::js::context::{ + AsContextMut, AsContextRef, ContextHandle, ContextObjects, InternalContextHandle, +}; +use crate::js::export::VMMemory; use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; -use crate::js::store::Store; use crate::js::{MemoryAccessError, MemoryType}; use std::convert::TryInto; +use std::marker::PhantomData; use std::mem::MaybeUninit; use std::slice; use thiserror::Error; @@ -77,8 +80,8 @@ extern "C" { /// Spec: #[derive(Debug, Clone)] pub struct Memory { - store: Store, - vm_memory: VMMemory, + pub(crate) handle: ContextHandle, + #[allow(dead_code)] view: js_sys::Uint8Array, } @@ -99,7 +102,7 @@ impl Memory { /// # /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); /// ``` - pub fn new(store: &Store, ty: MemoryType) -> Result { + pub fn new(ctx: &mut impl AsContextMut, ty: MemoryType) -> Result { let descriptor = js_sys::Object::new(); js_sys::Reflect::set(&descriptor, &"initial".into(), &ty.minimum.0.into()).unwrap(); if let Some(max) = ty.maximum { @@ -110,13 +113,8 @@ impl Memory { let js_memory = js_sys::WebAssembly::Memory::new(&descriptor) .map_err(|_e| MemoryError::Generic("Error while creating the memory".to_owned()))?; - let memory = VMMemory::new(js_memory, ty); - let view = js_sys::Uint8Array::new(&memory.memory.buffer()); - Ok(Self { - store: store.clone(), - vm_memory: memory, - view, - }) + let vm_memory = VMMemory::new(js_memory, ty); + Ok(Self::from_vm_export(ctx, vm_memory)) } /// Returns the [`MemoryType`] of the `Memory`. @@ -132,26 +130,8 @@ impl Memory { /// /// assert_eq!(m.ty(), mt); /// ``` - pub fn ty(&self) -> MemoryType { - let mut ty = self.vm_memory.ty.clone(); - ty.minimum = self.size(); - ty - } - - /// Returns the [`Store`] where the `Memory` belongs. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # let store = Store::default(); - /// # - /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); - /// - /// assert_eq!(m.store(), &store); - /// ``` - pub fn store(&self) -> &Store { - &self.store + pub fn ty(&self, ctx: &impl AsContextRef) -> MemoryType { + self.handle.get(ctx.as_context_ref().objects()).ty } /// Returns the pointer to the raw bytes of the `Memory`. @@ -161,11 +141,18 @@ impl Memory { } /// Returns the size (in bytes) of the `Memory`. - pub fn data_size(&self) -> u64 { - js_sys::Reflect::get(&self.vm_memory.memory.buffer(), &"byteLength".into()) - .unwrap() - .as_f64() - .unwrap() as _ + pub fn data_size(&self, ctx: &impl AsContextRef) -> u64 { + js_sys::Reflect::get( + &self + .handle + .get(ctx.as_context_ref().objects()) + .memory + .buffer(), + &"byteLength".into(), + ) + .unwrap() + .as_f64() + .unwrap() as _ } /// Returns the size (in [`Pages`]) of the `Memory`. @@ -180,11 +167,18 @@ impl Memory { /// /// assert_eq!(m.size(), Pages(1)); /// ``` - pub fn size(&self) -> Pages { - let bytes = js_sys::Reflect::get(&self.vm_memory.memory.buffer(), &"byteLength".into()) - .unwrap() - .as_f64() - .unwrap() as u64; + pub fn size(&self, ctx: &impl AsContextRef) -> Pages { + let bytes = js_sys::Reflect::get( + &self + .handle + .get(ctx.as_context_ref().objects()) + .memory + .buffer(), + &"byteLength".into(), + ) + .unwrap() + .as_f64() + .unwrap() as u64; Bytes(bytes as usize).try_into().unwrap() } @@ -218,16 +212,22 @@ impl Memory { /// // This results in an error: `MemoryError::CouldNotGrow`. /// let s = m.grow(1).unwrap(); /// ``` - pub fn grow(&self, delta: IntoPages) -> Result + pub fn grow( + &self, + ctx: &mut impl AsContextMut, + delta: IntoPages, + ) -> Result where IntoPages: Into, { let pages = delta.into(); - let js_memory = self.vm_memory.memory.clone().unchecked_into::(); - let new_pages = js_memory.grow(pages.0).map_err(|err| { + let mut ctx_mut = ctx.as_context_mut(); + let js_memory = &self.handle.get_mut(ctx_mut.objects_mut()).memory; + let our_js_memory: &JSMemory = JsCast::unchecked_from_js_ref(js_memory); + let new_pages = our_js_memory.grow(pages.0).map_err(|err| { if err.is_instance_of::() { MemoryError::CouldNotGrow { - current: self.size(), + current: self.size(&ctx.as_context_ref()), attempted_delta: pages, } } else { @@ -239,33 +239,43 @@ impl Memory { /// Used by tests #[doc(hidden)] - pub fn uint8view(&self) -> js_sys::Uint8Array { - js_sys::Uint8Array::new(&self.vm_memory.memory.buffer()) + pub fn uint8view(&self, ctx: &impl AsContextRef) -> js_sys::Uint8Array { + js_sys::Uint8Array::new( + &self + .handle + .get(ctx.as_context_ref().objects()) + .memory + .buffer(), + ) } - pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self { + pub(crate) fn buffer<'a>(&'a self, _ctx: &'a impl AsContextRef) -> MemoryBuffer<'a> { + MemoryBuffer { + base: &self.view as *const _ as *mut _, + marker: PhantomData, + } + } + + pub(crate) fn from_vm_export(ctx: &mut impl AsContextMut, vm_memory: VMMemory) -> Self { let view = js_sys::Uint8Array::new(&vm_memory.memory.buffer()); Self { - store: store.clone(), - vm_memory, + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_memory), view, } } - /// Returns whether or not these two memories refer to the same data. - /// - /// # Example - /// - /// ``` - /// # use wasmer::{Memory, MemoryType, Store, Value}; - /// # let store = Store::default(); - /// # - /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); - /// - /// assert!(m.same(&m)); - /// ``` - pub fn same(&self, other: &Self) -> bool { - self.vm_memory == other.vm_memory + pub(crate) fn from_vm_extern( + ctx: &mut impl AsContextMut, + internal: InternalContextHandle, + ) -> Self { + let view = + js_sys::Uint8Array::new(&internal.get(ctx.as_context_ref().objects()).memory.buffer()); + Self { + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, + view, + } } /// Safely reads bytes from the memory at the given offset. @@ -275,10 +285,15 @@ impl Memory { /// /// This method is guaranteed to be safe (from the host side) in the face of /// concurrent writes. - pub fn read(&self, offset: u64, buf: &mut [u8]) -> Result<(), MemoryAccessError> { - let view = self.uint8view(); + pub fn read( + &self, + _ctx: &impl AsContextRef, + offset: u64, + data: &mut [u8], + ) -> Result<(), MemoryAccessError> { + let view = &self.view; let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; - let len: u32 = buf + let len: u32 = data .len() .try_into() .map_err(|_| MemoryAccessError::Overflow)?; @@ -286,7 +301,7 @@ impl Memory { if end > view.length() { Err(MemoryAccessError::HeapOutOfBounds)?; } - view.subarray(offset, end).copy_to(buf); + view.subarray(offset, end).copy_to(data); Ok(()) } @@ -302,10 +317,11 @@ impl Memory { /// concurrent writes. pub fn read_uninit<'a>( &self, + _ctx: &impl AsContextRef, offset: u64, buf: &'a mut [MaybeUninit], ) -> Result<&'a mut [u8], MemoryAccessError> { - let view = self.uint8view(); + let view = &self.view; let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; let len: u32 = buf .len() @@ -334,14 +350,18 @@ impl Memory { /// /// This method is guaranteed to be safe (from the host side) in the face of /// concurrent reads/writes. - pub fn write(&self, offset: u64, data: &[u8]) -> Result<(), MemoryAccessError> { - let view = self.uint8view(); + pub fn write( + &self, + _ctx: &mut impl AsContextMut, + offset: u64, + data: &[u8], + ) -> Result<(), MemoryAccessError> { let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?; let len: u32 = data .len() .try_into() .map_err(|_| MemoryAccessError::Overflow)?; - let view = self.uint8view(); + let view = &self.view; let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?; if end > view.length() { Err(MemoryAccessError::HeapOutOfBounds)?; @@ -349,13 +369,14 @@ impl Memory { view.subarray(offset, end).copy_from(data); Ok(()) } -} -impl<'a> Exportable<'a> for Memory { - fn to_export(&self) -> Export { - Export::Memory(self.vm_memory.clone()) + /// Checks whether this `Global` can be used with the given context. + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } +} +impl<'a> Exportable<'a> for Memory { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Memory(memory) => Ok(memory), @@ -363,3 +384,57 @@ impl<'a> Exportable<'a> for Memory { } } } + +/// Underlying buffer for a memory. +#[derive(Copy, Clone)] +pub(crate) struct MemoryBuffer<'a> { + base: *mut js_sys::Uint8Array, + marker: PhantomData<(&'a Memory, &'a ContextObjects)>, +} + +impl<'a> MemoryBuffer<'a> { + pub(crate) fn read(&self, offset: u64, buf: &mut [u8]) -> Result<(), MemoryAccessError> { + let end = offset + .checked_add(buf.len() as u64) + .ok_or(MemoryAccessError::Overflow)?; + let view = unsafe { &*(self.base) }; + if end > view.length().into() { + return Err(MemoryAccessError::HeapOutOfBounds); + } + view.subarray(offset as _, end as _) + .copy_to(unsafe { &mut slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.len()) }); + Ok(()) + } + + pub(crate) fn read_uninit<'b>( + &self, + offset: u64, + buf: &'b mut [MaybeUninit], + ) -> Result<&'b mut [u8], MemoryAccessError> { + let end = offset + .checked_add(buf.len() as u64) + .ok_or(MemoryAccessError::Overflow)?; + let view = unsafe { &*(self.base) }; + if end > view.length().into() { + return Err(MemoryAccessError::HeapOutOfBounds); + } + let buf_ptr = buf.as_mut_ptr() as *mut u8; + view.subarray(offset as _, end as _) + .copy_to(unsafe { &mut slice::from_raw_parts_mut(buf_ptr, buf.len()) }); + + Ok(unsafe { slice::from_raw_parts_mut(buf_ptr, buf.len()) }) + } + + pub(crate) fn write(&self, offset: u64, data: &[u8]) -> Result<(), MemoryAccessError> { + let end = offset + .checked_add(data.len() as u64) + .ok_or(MemoryAccessError::Overflow)?; + let view = unsafe { &mut *(self.base) }; + if end > view.length().into() { + return Err(MemoryAccessError::HeapOutOfBounds); + } + view.subarray(offset as _, end as _).copy_from(data); + + Ok(()) + } +} diff --git a/lib/api/src/js/externals/mod.rs b/lib/api/src/js/externals/mod.rs index 33a5bc25d2a..03c76ada645 100644 --- a/lib/api/src/js/externals/mod.rs +++ b/lib/api/src/js/externals/mod.rs @@ -1,19 +1,18 @@ pub(crate) mod function; mod global; -mod memory; +pub(crate) mod memory; mod table; -pub use self::function::{ - FromToNativeWasmType, Function, HostFunction, WasmTypeList, WithEnv, WithoutEnv, -}; - +pub use self::function::{FromToNativeWasmType, Function, HostFunction, WasmTypeList}; pub use self::global::Global; pub use self::memory::{Memory, MemoryError}; pub use self::table::Table; +use crate::js::context::{AsContextMut, AsContextRef}; use crate::js::export::Export; use crate::js::exports::{ExportError, Exportable}; -use crate::js::store::{Store, StoreObject}; +use crate::js::store::StoreObject; +use crate::js::types::AsJs; use crate::js::ExternType; use std::fmt; @@ -35,36 +34,58 @@ pub enum Extern { impl Extern { /// Return the underlying type of the inner `Extern`. - pub fn ty(&self) -> ExternType { + pub fn ty(&self, ctx: &impl AsContextRef) -> ExternType { match self { - Self::Function(ft) => ExternType::Function(ft.ty().clone()), - Self::Memory(ft) => ExternType::Memory(ft.ty()), - Self::Table(tt) => ExternType::Table(*tt.ty()), - Self::Global(gt) => ExternType::Global(*gt.ty()), + Self::Function(ft) => ExternType::Function(ft.ty(ctx).clone()), + Self::Memory(ft) => ExternType::Memory(ft.ty(ctx)), + Self::Table(tt) => ExternType::Table(tt.ty(ctx)), + Self::Global(gt) => ExternType::Global(gt.ty(ctx)), } } /// Create an `Extern` from an `wasmer_compiler::Export`. - pub fn from_vm_export(store: &Store, export: Export) -> Self { + pub fn from_vm_export(ctx: &mut impl AsContextMut, export: Export) -> Self { match export { - Export::Function(f) => Self::Function(Function::from_vm_export(store, f)), - Export::Memory(m) => Self::Memory(Memory::from_vm_export(store, m)), - Export::Global(g) => Self::Global(Global::from_vm_export(store, g)), - Export::Table(t) => Self::Table(Table::from_vm_export(store, t)), + Export::Function(f) => Self::Function(Function::from_vm_extern(ctx, f)), + Export::Memory(m) => Self::Memory(Memory::from_vm_extern(ctx, m)), + Export::Global(g) => Self::Global(Global::from_vm_extern(ctx, g)), + Export::Table(t) => Self::Table(Table::from_vm_extern(ctx, t)), + } + } + + /// Checks whether this `Extern` can be used with the given context. + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + match self { + Self::Function(val) => val.is_from_context(ctx), + Self::Memory(val) => val.is_from_context(ctx), + Self::Global(val) => val.is_from_context(ctx), + Self::Table(val) => val.is_from_context(ctx), } } -} -impl<'a> Exportable<'a> for Extern { fn to_export(&self) -> Export { match self { - Self::Function(f) => f.to_export(), - Self::Global(g) => g.to_export(), - Self::Memory(m) => m.to_export(), - Self::Table(t) => t.to_export(), + Self::Function(val) => Export::Function(val.handle.internal_handle()), + Self::Memory(val) => Export::Memory(val.handle.internal_handle()), + Self::Global(val) => Export::Global(val.handle.internal_handle()), + Self::Table(val) => Export::Table(val.handle.internal_handle()), } } +} +impl AsJs for Extern { + fn as_jsvalue(&self, ctx: &impl AsContextRef) -> wasm_bindgen::JsValue { + match self { + Self::Function(_) => self.to_export().as_jsvalue(ctx), + Self::Global(_) => self.to_export().as_jsvalue(ctx), + Self::Table(_) => self.to_export().as_jsvalue(ctx), + Self::Memory(_) => self.to_export().as_jsvalue(ctx), + } + .clone() + } +} + +impl<'a> Exportable<'a> for Extern { fn get_self_from_extern(_extern: &'a Self) -> Result<&'a Self, ExportError> { // Since this is already an extern, we can just return it. Ok(_extern) diff --git a/lib/api/src/js/externals/table.rs b/lib/api/src/js/externals/table.rs index cc7608fee9b..f779b02d351 100644 --- a/lib/api/src/js/externals/table.rs +++ b/lib/api/src/js/externals/table.rs @@ -1,13 +1,11 @@ -use crate::js::export::VMFunction; -use crate::js::export::{Export, VMTable}; +use crate::js::context::{AsContextMut, AsContextRef, ContextHandle, InternalContextHandle}; +use crate::js::export::{VMFunction, VMTable}; use crate::js::exports::{ExportError, Exportable}; -use crate::js::externals::{Extern, Function as WasmerFunction}; -use crate::js::store::Store; -use crate::js::types::Val; +use crate::js::externals::Extern; +use crate::js::value::Value; use crate::js::RuntimeError; -use crate::js::TableType; +use crate::js::{FunctionType, TableType}; use js_sys::Function; -use wasmer_types::FunctionType; /// A WebAssembly `table` instance. /// @@ -20,17 +18,24 @@ use wasmer_types::FunctionType; /// Spec: #[derive(Debug, Clone, PartialEq)] pub struct Table { - store: Store, - vm_table: VMTable, + pub(crate) handle: ContextHandle, } fn set_table_item(table: &VMTable, item_index: u32, item: &Function) -> Result<(), RuntimeError> { table.table.set(item_index, item).map_err(|e| e.into()) } -fn get_function(val: Val) -> Result { +fn get_function(ctx: &mut impl AsContextMut, val: Value) -> Result { + if !val.is_from_context(ctx) { + return Err(RuntimeError::new("cannot pass Value across contexts")); + } match val { - Val::FuncRef(func) => Ok(func.as_ref().unwrap().exported.function.clone().into()), + Value::FuncRef(Some(ref func)) => Ok(func + .handle + .get(&ctx.as_context_ref().objects()) + .function + .clone() + .into()), // Only funcrefs is supported by the spec atm _ => unimplemented!(), } @@ -43,7 +48,12 @@ impl Table { /// /// This function will construct the `Table` using the store /// [`BaseTunables`][crate::js::tunables::BaseTunables]. - pub fn new(store: &Store, ty: TableType, init: Val) -> Result { + pub fn new( + ctx: &mut impl AsContextMut, + ty: TableType, + init: Value, + ) -> Result { + let mut ctx = ctx.as_context_mut(); let descriptor = js_sys::Object::new(); js_sys::Reflect::set(&descriptor, &"initial".into(), &ty.minimum.into())?; if let Some(max) = ty.maximum { @@ -55,47 +65,60 @@ impl Table { let table = VMTable::new(js_table, ty); let num_elements = table.table.length(); - let func = get_function(init)?; + let func = get_function(&mut ctx, init)?; for i in 0..num_elements { set_table_item(&table, i, &func)?; } Ok(Self { - store: store.clone(), - vm_table: table, + handle: ContextHandle::new(ctx.objects_mut(), table), }) } /// Returns the [`TableType`] of the `Table`. - pub fn ty(&self) -> &TableType { - &self.vm_table.ty - } - - /// Returns the [`Store`] where the `Table` belongs. - pub fn store(&self) -> &Store { - &self.store + pub fn ty(&self, ctx: &impl AsContextRef) -> TableType { + self.handle.get(ctx.as_context_ref().objects()).ty } /// Retrieves an element of the table at the provided `index`. - pub fn get(&self, index: u32) -> Option { - let func = self.vm_table.table.get(index).ok()?; - let ty = FunctionType::new(vec![], vec![]); - Some(Val::FuncRef(Some(WasmerFunction::from_vm_export( - &self.store, - VMFunction::new(func, ty, None), - )))) + pub fn get(&self, ctx: &mut impl AsContextMut, index: u32) -> Option { + if let Some(func) = self + .handle + .get(ctx.as_context_ref().objects()) + .table + .get(index) + .ok() + { + let ty = FunctionType::new(vec![], vec![]); + let vm_function = VMFunction::new(func, ty); + let function = crate::js::externals::Function::from_vm_export(ctx, vm_function); + Some(Value::FuncRef(Some(function))) + } else { + None + } } /// Sets an element `val` in the Table at the provided `index`. - pub fn set(&self, index: u32, val: Val) -> Result<(), RuntimeError> { - let func = get_function(val)?; - set_table_item(&self.vm_table, index, &func)?; - Ok(()) + pub fn set( + &self, + ctx: &mut impl AsContextMut, + index: u32, + val: Value, + ) -> Result<(), RuntimeError> { + let item = get_function(ctx, val)?; + set_table_item( + self.handle.get_mut(ctx.as_context_mut().objects_mut()), + index, + &item, + ) } /// Retrieves the size of the `Table` (in elements) - pub fn size(&self) -> u32 { - self.vm_table.table.length() + pub fn size(&self, ctx: &impl AsContextRef) -> u32 { + self.handle + .get(ctx.as_context_ref().objects()) + .table + .length() } /// Grows the size of the `Table` by `delta`, initializating @@ -107,7 +130,7 @@ impl Table { /// # Errors /// /// Returns an error if the `delta` is out of bounds for the table. - pub fn grow(&self, _delta: u32, _init: Val) -> Result { + pub fn grow(&self, _delta: u32, _init: Value) -> Result { unimplemented!(); } @@ -128,16 +151,20 @@ impl Table { unimplemented!("Table.copy is not natively supported in Javascript"); } - pub(crate) fn from_vm_export(store: &Store, vm_table: VMTable) -> Self { + pub(crate) fn from_vm_extern( + ctx: &mut impl AsContextMut, + internal: InternalContextHandle, + ) -> Self { Self { - store: store.clone(), - vm_table, + handle: unsafe { + ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + }, } } - /// Returns whether or not these two tables refer to the same data. - pub fn same(&self, other: &Self) -> bool { - self.vm_table == other.vm_table + /// Checks whether this `Table` can be used with the given context. + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + self.handle.context_id() == ctx.as_context_ref().objects().id() } /// Get access to the backing VM value for this extern. This function is for @@ -148,16 +175,15 @@ impl Table { /// because there is no stability guarantee for the returned type and we may /// make breaking changes to it at any time or remove this method. #[doc(hidden)] - pub unsafe fn get_vm_table(&self) -> &VMTable { - &self.vm_table + pub unsafe fn get_vm_table<'context>( + &self, + ctx: &'context impl AsContextRef, + ) -> &'context VMTable { + self.handle.get(ctx.as_context_ref().objects()) } } impl<'a> Exportable<'a> for Table { - fn to_export(&self) -> Export { - Export::Table(self.vm_table.clone()) - } - fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { Extern::Table(table) => Ok(table), diff --git a/lib/api/src/js/imports.rs b/lib/api/src/js/imports.rs index e1543e66ea9..596336e62ef 100644 --- a/lib/api/src/js/imports.rs +++ b/lib/api/src/js/imports.rs @@ -1,9 +1,11 @@ //! The import module contains the implementation data structures and helper functions used to //! manipulate and access a wasm module's imports including memories, tables, globals, and //! functions. -use crate::js::exports::{Exportable, Exports}; -use crate::js::instance::InstantiationError; +use crate::js::context::AsContextRef; +use crate::js::error::InstantiationError; +use crate::js::exports::Exports; use crate::js::module::Module; +use crate::js::types::AsJs; use crate::Extern; use std::collections::HashMap; use std::fmt; @@ -149,7 +151,7 @@ impl Imports { } /// Returns the `Imports` as a Javascript `Object` - pub fn as_jsobject(&self) -> js_sys::Object { + pub fn as_jsobject(&self, ctx: &impl AsContextRef) -> js_sys::Object { let imports = js_sys::Object::new(); let namespaces: HashMap<&str, Vec<(&str, &Extern)>> = self.map @@ -164,12 +166,8 @@ impl Imports { for (ns, exports) in namespaces.into_iter() { let import_namespace = js_sys::Object::new(); for (name, ext) in exports { - js_sys::Reflect::set( - &import_namespace, - &name.into(), - ext.to_export().as_jsvalue(), - ) - .expect("Error while setting into the js namespace object"); + js_sys::Reflect::set(&import_namespace, &name.into(), &ext.as_jsvalue(ctx)) + .expect("Error while setting into the js namespace object"); } js_sys::Reflect::set(&imports, &ns.into(), &import_namespace.into()) .expect("Error while setting into the js imports object"); @@ -178,12 +176,6 @@ impl Imports { } } -impl Into for Imports { - fn into(self) -> js_sys::Object { - self.as_jsobject() - } -} - impl IntoIterator for &Imports { type IntoIter = std::collections::hash_map::IntoIter<(String, String), Extern>; type Item = ((String, String), Extern); @@ -299,15 +291,14 @@ macro_rules! import_namespace { }; } -#[cfg(test)] +/* mod test { - use crate::js::export::Export; use crate::js::exports::Exportable; use crate::js::Type; use crate::js::{Global, Store, Val}; - use wasm_bindgen_test::*; - #[wasm_bindgen_test] + use crate::js::export::Export; + use wasm_bindgen_test::*; fn namespace() { let store = Store::default(); let g1 = Global::new(&store, Val::I32(0)); @@ -329,7 +320,6 @@ mod test { ); } - #[wasm_bindgen_test] fn imports_macro_allows_trailing_comma_and_none() { use crate::js::Function; @@ -381,7 +371,6 @@ mod test { }; } - #[wasm_bindgen_test] fn chaining_works() { let store = Store::default(); let g = Global::new(&store, Val::I32(0)); @@ -412,7 +401,6 @@ mod test { assert!(small.is_some()); } - #[wasm_bindgen_test] fn extending_conflict_overwrites() { let store = Store::default(); let g1 = Global::new(&store, Val::I32(0)); @@ -470,3 +458,4 @@ mod test { ); } } + */ diff --git a/lib/api/src/js/instance.rs b/lib/api/src/js/instance.rs index afbf23d11f8..ca2c830d7e3 100644 --- a/lib/api/src/js/instance.rs +++ b/lib/api/src/js/instance.rs @@ -1,15 +1,12 @@ -use crate::js::env::HostEnvInitError; +use crate::js::context::{AsContextMut, AsContextRef, ContextHandle}; +use crate::js::error::InstantiationError; use crate::js::export::Export; -use crate::js::exports::{Exportable, Exports}; +use crate::js::exports::Exports; use crate::js::externals::Extern; use crate::js::imports::Imports; use crate::js::module::Module; -use crate::js::store::Store; -use crate::js::trap::RuntimeError; use js_sys::WebAssembly; use std::fmt; -#[cfg(feature = "std")] -use thiserror::Error; /// A WebAssembly Instance is a stateful, executable /// instance of a WebAssembly [`Module`]. @@ -21,7 +18,7 @@ use thiserror::Error; /// Spec: #[derive(Clone)] pub struct Instance { - instance: WebAssembly::Instance, + _handle: ContextHandle, module: Module, #[allow(dead_code)] imports: Imports, @@ -29,37 +26,6 @@ pub struct Instance { pub exports: Exports, } -/// An error while instantiating a module. -/// -/// This is not a common WebAssembly error, however -/// we need to differentiate from a `LinkError` (an error -/// that happens while linking, on instantiation), a -/// Trap that occurs when calling the WebAssembly module -/// start function, and an error when initializing the user's -/// host environments. -#[derive(Debug)] -#[cfg_attr(feature = "std", derive(Error))] -pub enum InstantiationError { - /// A linking ocurred during instantiation. - #[cfg_attr(feature = "std", error("Link error: {0}"))] - Link(String), - - /// A runtime error occured while invoking the start function - #[cfg_attr(feature = "std", error(transparent))] - Start(RuntimeError), - - /// Error occurred when initializing the host environment. - #[cfg_attr(feature = "std", error(transparent))] - HostEnvInitialization(HostEnvInitError), -} - -#[cfg(feature = "core")] -impl std::fmt::Display for InstantiationError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "InstantiationError") - } -} - impl Instance { /// Creates a new `Instance` from a WebAssembly [`Module`] and a /// set of imports resolved by the [`Resolver`]. @@ -94,14 +60,18 @@ impl Instance { /// Those are, as defined by the spec: /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. - pub fn new(module: &Module, imports: &Imports) -> Result { + pub fn new( + ctx: &mut impl AsContextMut, + module: &Module, + imports: &Imports, + ) -> Result { let import_copy = imports.clone(); - let (instance, imports): (WebAssembly::Instance, Vec) = module - .instantiate(imports) + let (instance, _imports): (ContextHandle, Vec) = module + .instantiate(&mut ctx.as_context_mut(), imports) .map_err(|e| InstantiationError::Start(e))?; - let self_instance = Self::from_module_and_instance(module, instance, import_copy)?; - self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::>())?; + let self_instance = Self::from_module_and_instance(ctx, module, instance, import_copy)?; + //self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::>())?; Ok(self_instance) } @@ -115,12 +85,12 @@ impl Instance { /// /// *This method is only available when targeting JS environments* pub fn from_module_and_instance( + ctx: &mut impl AsContextMut, module: &Module, - instance: WebAssembly::Instance, + instance: ContextHandle, imports: Imports, ) -> Result { - let store = module.store(); - let instance_exports = instance.exports(); + let instance_exports = instance.get(ctx.as_context_ref().objects()).exports(); let exports = module .exports() .map(|export_type| { @@ -133,53 +103,34 @@ impl Instance { &name )) })?; - let export: Export = (js_export, extern_type).into(); - let extern_ = Extern::from_vm_export(store, export); + let export: Export = + Export::from_js_value(js_export, &mut ctx.as_context_mut(), extern_type)? + .into(); + let extern_ = Extern::from_vm_export(&mut ctx.as_context_mut(), export); Ok((name.to_string(), extern_)) }) .collect::>()?; Ok(Self { - instance, + _handle: instance, module: module.clone(), imports, exports, }) } - /// Initialize the given extern imports with the `Instance`. - /// - /// # Important - /// - /// This method should be called if the Wasmer `Instance` is initialized - /// from Javascript with an already existing `WebAssembly.Instance` but with - /// a imports from the Rust side. - /// - /// *This method is only available when targeting JS environments* - pub fn init_envs(&self, imports: &[Export]) -> Result<(), InstantiationError> { - for import in imports { - if let Export::Function(func) = import { - func.init_envs(&self) - .map_err(|e| InstantiationError::HostEnvInitialization(e))?; - } - } - Ok(()) - } - /// Gets the [`Module`] associated with this instance. pub fn module(&self) -> &Module { &self.module } - /// Returns the [`Store`] where the `Instance` belongs. - pub fn store(&self) -> &Store { - self.module.store() - } - /// Returns the inner WebAssembly Instance #[doc(hidden)] - pub fn raw(&self) -> &WebAssembly::Instance { - &self.instance + pub fn raw<'context>( + &self, + ctx: &'context impl AsContextRef, + ) -> &'context WebAssembly::Instance { + &self._handle.get(ctx.as_context_ref().objects()) } } diff --git a/lib/api/src/js/js_import_object.rs b/lib/api/src/js/js_import_object.rs index 98c0c33c85a..f1e58aec906 100644 --- a/lib/api/src/js/js_import_object.rs +++ b/lib/api/src/js/js_import_object.rs @@ -1,3 +1,5 @@ +use crate::js::context::AsContextMut; +use crate::js::error::WasmError; use crate::js::{Export, ExternType, Module}; use std::collections::HashMap; @@ -49,15 +51,23 @@ impl JsImportObject { /// let import_object = JsImportObject::new(&module, js_object); /// import_object.get_export("module", "name"); /// ``` - pub fn get_export(&self, module: &str, name: &str) -> Option { - let namespace = js_sys::Reflect::get(&self.object, &module.into()).ok()?; - let js_export = js_sys::Reflect::get(&namespace, &name.into()).ok()?; + pub fn get_export( + &self, + ctx: &mut impl AsContextMut, + module: &str, + name: &str, + ) -> Result { + let namespace = js_sys::Reflect::get(&self.object, &module.into())?; + let js_export = js_sys::Reflect::get(&namespace, &name.into())?; match self .module_imports .get(&(module.to_string(), name.to_string())) { - Some(extern_type) => Some((js_export, extern_type.clone()).into()), - None => None, + Some(extern_type) => Ok(Export::from_js_value(js_export, ctx, extern_type.clone())?), + None => Err(WasmError::Generic(format!( + "Name {} not found in module {}", + name, module + ))), } } } diff --git a/lib/api/src/js/mem_access.rs b/lib/api/src/js/mem_access.rs index 9c7cbef967c..e5eb45afb0a 100644 --- a/lib/api/src/js/mem_access.rs +++ b/lib/api/src/js/mem_access.rs @@ -1,3 +1,5 @@ +use crate::js::context::AsContextRef; +use crate::js::externals::memory::MemoryBuffer; use crate::RuntimeError; use crate::{Memory, Memory32, Memory64, WasmPtr}; use std::{ @@ -51,7 +53,7 @@ impl From for MemoryAccessError { /// thread. #[derive(Clone, Copy)] pub struct WasmRef<'a, T: ValueType> { - memory: &'a Memory, + buffer: MemoryBuffer<'a>, offset: u64, marker: PhantomData<*mut T>, } @@ -59,9 +61,9 @@ pub struct WasmRef<'a, T: ValueType> { impl<'a, T: ValueType> WasmRef<'a, T> { /// Creates a new `WasmRef` at the given offset in a memory. #[inline] - pub fn new(memory: &'a Memory, offset: u64) -> Self { + pub fn new(ctx: &'a impl AsContextRef, memory: &'a Memory, offset: u64) -> Self { Self { - memory, + buffer: memory.buffer(ctx), offset, marker: PhantomData, } @@ -96,19 +98,13 @@ impl<'a, T: ValueType> WasmRef<'a, T> { WasmPtr::::new(offset) } - /// Get a reference to the Wasm memory backing this reference. - #[inline] - pub fn memory(self) -> &'a Memory { - self.memory - } - /// Reads the location pointed to by this `WasmRef`. #[inline] pub fn read(self) -> Result { let mut out = MaybeUninit::uninit(); let buf = unsafe { slice::from_raw_parts_mut(out.as_mut_ptr() as *mut u8, mem::size_of::()) }; - self.memory.read(self.offset, buf)?; + self.buffer.read(self.offset, buf)?; Ok(unsafe { out.assume_init() }) } @@ -124,7 +120,7 @@ impl<'a, T: ValueType> WasmRef<'a, T> { }; val.zero_padding_bytes(data); let data = unsafe { slice::from_raw_parts(data.as_ptr() as *const _, data.len()) }; - self.memory.write(self.offset, data) + self.buffer.write(self.offset, data) } } @@ -151,7 +147,7 @@ impl<'a, T: ValueType> fmt::Debug for WasmRef<'a, T> { /// thread. #[derive(Clone, Copy)] pub struct WasmSlice<'a, T: ValueType> { - memory: &'a Memory, + buffer: MemoryBuffer<'a>, offset: u64, len: u64, marker: PhantomData<*mut T>, @@ -163,7 +159,12 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { /// /// Returns a `MemoryAccessError` if the slice length overflows. #[inline] - pub fn new(memory: &'a Memory, offset: u64, len: u64) -> Result { + pub fn new( + ctx: &'a impl AsContextRef, + memory: &'a Memory, + offset: u64, + len: u64, + ) -> Result { let total_len = len .checked_mul(mem::size_of::() as u64) .ok_or(MemoryAccessError::Overflow)?; @@ -171,7 +172,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { .checked_add(total_len) .ok_or(MemoryAccessError::Overflow)?; Ok(Self { - memory, + buffer: memory.buffer(ctx), offset, len, marker: PhantomData, @@ -202,12 +203,6 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { self.len } - /// Get a reference to the Wasm memory backing this reference. - #[inline] - pub fn memory(self) -> &'a Memory { - self.memory - } - /// Get a `WasmRef` to an element in the slice. #[inline] pub fn index(self, idx: u64) -> WasmRef<'a, T> { @@ -216,7 +211,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { } let offset = self.offset + idx * mem::size_of::() as u64; WasmRef { - memory: self.memory, + buffer: self.buffer, offset, marker: PhantomData, } @@ -230,7 +225,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { } let offset = self.offset + range.start * mem::size_of::() as u64; Self { - memory: self.memory, + buffer: self.buffer, offset, len: range.end - range.start, marker: PhantomData, @@ -271,7 +266,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { buf.len() * mem::size_of::(), ) }; - self.memory.read_uninit(self.offset, bytes)?; + self.buffer.read_uninit(self.offset, bytes)?; Ok(()) } @@ -296,7 +291,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { buf.len() * mem::size_of::(), ) }; - self.memory.read_uninit(self.offset, bytes)?; + self.buffer.read_uninit(self.offset, bytes)?; Ok(unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut T, buf.len()) }) } @@ -313,7 +308,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { let bytes = unsafe { slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * mem::size_of::()) }; - self.memory.write(self.offset, bytes) + self.buffer.write(self.offset, bytes) } /// Reads this `WasmSlice` into a `Vec`. @@ -327,7 +322,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { len * mem::size_of::(), ) }; - self.memory.read_uninit(self.offset, bytes)?; + self.buffer.read_uninit(self.offset, bytes)?; unsafe { vec.set_len(len); } diff --git a/lib/api/src/js/mod.rs b/lib/api/src/js/mod.rs index 74c01f2060d..8f75409a87f 100644 --- a/lib/api/src/js/mod.rs +++ b/lib/api/src/js/mod.rs @@ -23,7 +23,7 @@ mod lib { } } -mod env; +mod context; mod error; mod export; mod exports; @@ -36,19 +36,16 @@ mod module; #[cfg(feature = "wasm-types-polyfill")] mod module_info_polyfill; mod native; +mod native_type; mod ptr; mod store; mod trap; mod types; +mod value; mod wasm_bindgen_polyfill; -/// Implement [`WasmerEnv`] for your type with `#[derive(WasmerEnv)]`. -/// -/// See the [`WasmerEnv`] trait for more information. -pub use wasmer_derive::WasmerEnv; - -pub use crate::js::env::{HostEnvInitError, LazyInit, WasmerEnv}; -pub use crate::js::error::{DeserializeError, SerializeError}; +pub use crate::js::context::{AsContextMut, AsContextRef, Context, ContextMut, ContextRef}; +pub use crate::js::error::{DeserializeError, InstantiationError, SerializeError}; pub use crate::js::export::Export; pub use crate::js::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::js::externals::{ @@ -56,20 +53,23 @@ pub use crate::js::externals::{ WasmTypeList, }; pub use crate::js::imports::Imports; -pub use crate::js::instance::{Instance, InstantiationError}; +pub use crate::js::instance::Instance; pub use crate::js::js_import_object::JsImportObject; pub use crate::js::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter}; pub use crate::js::module::{Module, ModuleTypeHints}; pub use crate::js::native::TypedFunction; +pub use crate::js::native_type::NativeWasmTypeInto; pub use crate::js::ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64}; pub use crate::js::trap::RuntimeError; pub use crate::js::store::{Store, StoreObject}; +pub use crate::js::types::ValType as Type; pub use crate::js::types::{ ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, - TableType, Val, ValType, + TableType, ValType, }; -pub use crate::js::types::{Val as Value, ValType as Type}; +pub use crate::js::value::Value; +pub use crate::js::value::Value as Val; pub use wasmer_types::is_wasm; pub use wasmer_types::{ diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index 1828ca83945..67ef83b9aa1 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -1,14 +1,13 @@ -use crate::js::exports::Exportable; -use crate::js::externals::Extern; -use crate::js::imports::Imports; -use crate::js::store::Store; -use crate::js::types::{ExportType, ImportType}; -// use crate::js::InstantiationError; -use crate::js::error::CompileError; +use crate::js::context::{AsContextMut, ContextHandle}; #[cfg(feature = "wat")] use crate::js::error::WasmError; +use crate::js::error::{CompileError, InstantiationError}; #[cfg(feature = "js-serializable-module")] use crate::js::error::{DeserializeError, SerializeError}; +use crate::js::externals::Extern; +use crate::js::imports::Imports; +use crate::js::store::Store; +use crate::js::types::{AsJs, ExportType, ImportType}; use crate::js::RuntimeError; use js_sys::{Reflect, Uint8Array, WebAssembly}; use std::fmt; @@ -220,8 +219,17 @@ impl Module { pub(crate) fn instantiate( &self, + ctx: &mut impl AsContextMut, imports: &Imports, - ) -> Result<(WebAssembly::Instance, Vec), RuntimeError> { + ) -> Result<(ContextHandle, Vec), RuntimeError> { + // Ensure all imports come from the same context. + if imports + .into_iter() + .any(|(_, import)| !import.is_from_context(ctx)) + { + // FIXME is RuntimeError::User appropriate? + return Err(RuntimeError::user(Box::new(InstantiationError::BadContext))); + } let imports_object = js_sys::Object::new(); let mut import_externs: Vec = vec![]; for import_type in self.imports() { @@ -233,7 +241,7 @@ impl Module { js_sys::Reflect::set( &val, &import_type.name().into(), - import.to_export().as_jsvalue(), + &import.as_jsvalue(&ctx.as_context_ref()), )?; } else { // If the namespace doesn't exist @@ -241,7 +249,7 @@ impl Module { js_sys::Reflect::set( &import_namespace, &import_type.name().into(), - import.to_export().as_jsvalue(), + &import.as_jsvalue(&ctx.as_context_ref()), )?; js_sys::Reflect::set( &imports_object, @@ -255,8 +263,11 @@ impl Module { // the error for us, so we don't need to handle it } Ok(( - WebAssembly::Instance::new(&self.module, &imports_object) - .map_err(|e: JsValue| -> RuntimeError { e.into() })?, + ContextHandle::new( + ctx.as_context_mut().objects_mut(), + WebAssembly::Instance::new(&self.module, &imports_object) + .map_err(|e: JsValue| -> RuntimeError { e.into() })?, + ), import_externs, )) } diff --git a/lib/api/src/js/native.rs b/lib/api/src/js/native.rs index c99037b9fd8..ca21f752301 100644 --- a/lib/api/src/js/native.rs +++ b/lib/api/src/js/native.rs @@ -9,7 +9,9 @@ //! ``` use std::marker::PhantomData; -use crate::js::{FromToNativeWasmType, Function, RuntimeError, Store, WasmTypeList}; +use crate::js::context::{AsContextMut, AsContextRef, ContextHandle}; +use crate::js::externals::Function; +use crate::js::{FromToNativeWasmType, RuntimeError, WasmTypeList}; // use std::panic::{catch_unwind, AssertUnwindSafe}; use crate::js::export::VMFunction; use crate::js::types::param_from_js; @@ -21,8 +23,7 @@ use wasm_bindgen::JsValue; /// (using the Native ABI). #[derive(Clone)] pub struct TypedFunction { - store: Store, - exported: VMFunction, + pub(crate) handle: ContextHandle, _phantom: PhantomData<(Args, Rets)>, } @@ -34,34 +35,18 @@ where Args: WasmTypeList, Rets: WasmTypeList, { - pub(crate) fn new(store: Store, exported: VMFunction) -> Self { + #[allow(dead_code)] + pub(crate) fn new(ctx: &mut impl AsContextMut, vm_function: VMFunction) -> Self { Self { - store, - exported, + handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), _phantom: PhantomData, } } -} -impl From<&TypedFunction> for VMFunction -where - Args: WasmTypeList, - Rets: WasmTypeList, -{ - fn from(other: &TypedFunction) -> Self { - other.exported.clone() - } -} - -impl From> for Function -where - Args: WasmTypeList, - Rets: WasmTypeList, -{ - fn from(other: TypedFunction) -> Self { + pub(crate) fn from_handle(f: Function) -> Self { Self { - store: other.store, - exported: other.exported, + handle: f.handle, + _phantom: PhantomData, } } } @@ -75,20 +60,23 @@ macro_rules! impl_native_traits { Rets: WasmTypeList, { /// Call the typed func and return results. - pub fn call(&self, $( $x: $x, )* ) -> Result { - let params_list: Vec = vec![ $( JsValue::from_f64($x.to_native().to_binary() as f64) ),* ]; - let results = self.exported.function.apply( + #[allow(clippy::too_many_arguments)] + pub fn call(&self, ctx: &mut impl AsContextMut, $( $x: $x, )* ) -> Result where + $( $x: FromToNativeWasmType + crate::js::NativeWasmTypeInto, )* + { + let params_list: Vec = vec![ $( JsValue::from_f64($x.into_raw(ctx))),* ]; + let results = self.handle.get(ctx.as_context_ref().objects()).function.apply( &JsValue::UNDEFINED, &Array::from_iter(params_list.iter()) )?; let mut rets_list_array = Rets::empty_array(); - let mut_rets = rets_list_array.as_mut() as *mut [i128] as *mut i128; + let mut_rets = rets_list_array.as_mut() as *mut [f64] as *mut f64; match Rets::size() { 0 => {}, 1 => unsafe { let ty = Rets::wasm_types()[0]; let val = param_from_js(&ty, &results); - val.write_value_to(mut_rets); + *mut_rets = val.as_raw(&mut ctx.as_context_mut()); } _n => { let results: Array = results.into(); @@ -96,12 +84,13 @@ macro_rules! impl_native_traits { let ret = results.get(i as u32); unsafe { let val = param_from_js(&ret_type, &ret); - val.write_value_to(mut_rets.add(i)); + let slot = mut_rets.add(i); + *slot = val.as_raw(&mut ctx.as_context_mut()); } } } } - Ok(Rets::from_array(rets_list_array)) + Ok(unsafe { Rets::from_array(ctx, rets_list_array) }) } } @@ -112,9 +101,9 @@ macro_rules! impl_native_traits { $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, { - fn get_self_from_extern_with_generics(_extern: &crate::js::externals::Extern) -> Result { + fn get_self_from_extern_with_generics(ctx: &impl AsContextRef, _extern: &crate::js::externals::Extern) -> Result { use crate::js::exports::Exportable; - crate::js::Function::get_self_from_extern(_extern)?.native().map_err(|_| crate::js::exports::ExportError::IncompatibleType) + crate::js::Function::get_self_from_extern(_extern)?.native(ctx).map_err(|_| crate::js::exports::ExportError::IncompatibleType) } } }; diff --git a/lib/api/src/js/native_type.rs b/lib/api/src/js/native_type.rs new file mode 100644 index 00000000000..e6dc2805462 --- /dev/null +++ b/lib/api/src/js/native_type.rs @@ -0,0 +1,160 @@ +//! This module permits to create native functions +//! easily in Rust, thanks to its advanced typing system. + +use wasmer_types::{NativeWasmType, Type}; + +use crate::Function; + +use super::context::AsContextMut; + +/// `NativeWasmTypeInto` performs conversions from and into `NativeWasmType` +/// types with a context. +pub trait NativeWasmTypeInto: NativeWasmType + Sized { + #[doc(hidden)] + fn into_abi(self, ctx: &mut impl AsContextMut) -> Self::Abi; + + #[doc(hidden)] + unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self; + + /// Convert self to raw value representation. + fn into_raw(self, ctx: &mut impl AsContextMut) -> f64; + + /// Convert to self from raw value representation. + /// + /// # Safety + /// + unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: f64) -> Self; +} + +impl NativeWasmTypeInto for i32 { + #[inline] + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + self.into() + } + + #[inline] + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + raw as _ + } +} + +impl NativeWasmTypeInto for i64 { + #[inline] + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + self as _ + } + + #[inline] + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + raw as _ + } +} + +impl NativeWasmTypeInto for f32 { + #[inline] + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + self as _ + } + + #[inline] + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + raw as _ + } +} + +impl NativeWasmTypeInto for f64 { + #[inline] + unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + abi + } + + #[inline] + fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + self + } + + #[inline] + fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + self + } + + #[inline] + unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + raw + } +} + +impl NativeWasmType for Function { + const WASM_TYPE: Type = Type::FuncRef; + type Abi = f64; +} + +/* +mod test_native_type { + use super::*; + use wasmer_types::Type; + + fn test_wasm_types() { + assert_eq!(i32::WASM_TYPE, Type::I32); + assert_eq!(i64::WASM_TYPE, Type::I64); + assert_eq!(f32::WASM_TYPE, Type::F32); + assert_eq!(f64::WASM_TYPE, Type::F64); + } + + fn test_roundtrip() { + unsafe { + assert_eq!(i32::from_raw(42i32.into_raw()), 42i32); + assert_eq!(i64::from_raw(42i64.into_raw()), 42i64); + assert_eq!(f32::from_raw(42f32.into_raw()), 42f32); + assert_eq!(f64::from_raw(42f64.into_raw()), 42f64); + } + } +} + */ + +// pub trait IntegerAtomic +// where +// Self: Sized +// { +// type Primitive; + +// fn add(&self, other: Self::Primitive) -> Self::Primitive; +// fn sub(&self, other: Self::Primitive) -> Self::Primitive; +// fn and(&self, other: Self::Primitive) -> Self::Primitive; +// fn or(&self, other: Self::Primitive) -> Self::Primitive; +// fn xor(&self, other: Self::Primitive) -> Self::Primitive; +// fn load(&self) -> Self::Primitive; +// fn store(&self, other: Self::Primitive) -> Self::Primitive; +// fn compare_exchange(&self, expected: Self::Primitive, new: Self::Primitive) -> Self::Primitive; +// fn swap(&self, other: Self::Primitive) -> Self::Primitive; +// } diff --git a/lib/api/src/js/ptr.rs b/lib/api/src/js/ptr.rs index 36d76481bf2..95a1f8f1704 100644 --- a/lib/api/src/js/ptr.rs +++ b/lib/api/src/js/ptr.rs @@ -1,3 +1,5 @@ +use crate::js::context::AsContextRef; +use crate::js::NativeWasmTypeInto; use crate::js::{externals::Memory, FromToNativeWasmType}; use crate::{MemoryAccessError, WasmRef, WasmSlice}; use std::convert::TryFrom; @@ -136,20 +138,25 @@ impl WasmPtr { /// Creates a `WasmRef` from this `WasmPtr` which allows reading and /// mutating of the value being pointed to. #[inline] - pub fn deref<'a>(self, memory: &'a Memory) -> WasmRef<'a, T> { - WasmRef::new(memory, self.offset.into()) + pub fn deref<'a>(self, ctx: &'a impl AsContextRef, memory: &'a Memory) -> WasmRef<'a, T> { + WasmRef::new(ctx, memory, self.offset.into()) } /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, memory: &Memory) -> Result { - self.deref(memory).read() + pub fn read(self, ctx: &impl AsContextRef, memory: &Memory) -> Result { + self.deref(ctx, memory).read() } /// Writes to the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn write(self, memory: &Memory, val: T) -> Result<(), MemoryAccessError> { - self.deref(memory).write(val) + pub fn write( + self, + ctx: &impl AsContextRef, + memory: &Memory, + val: T, + ) -> Result<(), MemoryAccessError> { + self.deref(ctx, memory).write(val) } /// Creates a `WasmSlice` starting at this `WasmPtr` which allows reading @@ -160,10 +167,11 @@ impl WasmPtr { #[inline] pub fn slice<'a>( self, + ctx: &'a impl AsContextRef, memory: &'a Memory, len: M::Offset, ) -> Result, MemoryAccessError> { - WasmSlice::new(memory, self.offset.into(), len.into()) + WasmSlice::new(ctx, memory, self.offset.into(), len.into()) } /// Reads a sequence of values from this `WasmPtr` until a value that @@ -173,13 +181,14 @@ impl WasmPtr { #[inline] pub fn read_until<'a>( self, + ctx: &'a impl AsContextRef, memory: &'a Memory, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { let mut vec = Vec::new(); for i in 0u64.. { let i = M::Offset::try_from(i).map_err(|_| MemoryAccessError::Overflow)?; - let val = self.add_offset(i)?.deref(memory).read()?; + let val = self.add_offset(i)?.deref(ctx, memory).read()?; if end(&val) { break; } @@ -197,10 +206,11 @@ impl WasmPtr { #[inline] pub fn read_utf8_string<'a>( self, + ctx: &'a impl AsContextRef, memory: &'a Memory, len: M::Offset, ) -> Result { - let vec = self.slice(memory, len)?.read_to_vec()?; + let vec = self.slice(ctx, memory, len)?.read_to_vec()?; Ok(String::from_utf8(vec)?) } @@ -211,14 +221,18 @@ impl WasmPtr { #[inline] pub fn read_utf8_string_with_nul<'a>( self, + ctx: &'a impl AsContextRef, memory: &'a Memory, ) -> Result { - let vec = self.read_until(memory, |&byte| byte == 0)?; + let vec = self.read_until(ctx, memory, |&byte| byte == 0)?; Ok(String::from_utf8(vec)?) } } -unsafe impl FromToNativeWasmType for WasmPtr { +unsafe impl FromToNativeWasmType for WasmPtr +where + ::Native: NativeWasmTypeInto, +{ type Native = M::Native; fn to_native(self) -> Self::Native { diff --git a/lib/api/src/js/types.rs b/lib/api/src/js/types.rs index 8b9723987f8..baf52038ddd 100644 --- a/lib/api/src/js/types.rs +++ b/lib/api/src/js/types.rs @@ -1,8 +1,9 @@ -use crate::js::externals::Function; +//use crate::js::externals::Function; // use crate::js::store::{Store, StoreObject}; // use crate::js::RuntimeError; +use crate::js::context::AsContextRef; +use crate::js::value::Value; use wasm_bindgen::JsValue; -use wasmer_types::Value; pub use wasmer_types::{ ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, TableType, Type as ValType, @@ -14,20 +15,20 @@ pub use wasmer_types::{ /// * Vectors (128 bits, with 32 or 64 bit lanes) /// /// Spec: -// pub type Val = (); -pub type Val = Value; +// pub type Value = (); +//pub type Value = Value; pub trait AsJs { - fn as_jsvalue(&self) -> JsValue; + fn as_jsvalue(&self, ctx: &impl AsContextRef) -> JsValue; } #[inline] -pub fn param_from_js(ty: &ValType, js_val: &JsValue) -> Val { +pub fn param_from_js(ty: &ValType, js_val: &JsValue) -> Value { match ty { - ValType::I32 => Val::I32(js_val.as_f64().unwrap() as _), - ValType::I64 => Val::I64(js_val.as_f64().unwrap() as _), - ValType::F32 => Val::F32(js_val.as_f64().unwrap() as _), - ValType::F64 => Val::F64(js_val.as_f64().unwrap()), + ValType::I32 => Value::I32(js_val.as_f64().unwrap() as _), + ValType::I64 => Value::I64(js_val.as_f64().unwrap() as _), + ValType::F32 => Value::F32(js_val.as_f64().unwrap() as _), + ValType::F64 => Value::F64(js_val.as_f64().unwrap()), t => unimplemented!( "The type `{:?}` is not yet supported in the JS Function API", t @@ -35,18 +36,20 @@ pub fn param_from_js(ty: &ValType, js_val: &JsValue) -> Val { } } -impl AsJs for Val { - fn as_jsvalue(&self) -> JsValue { +impl AsJs for Value { + fn as_jsvalue(&self, ctx: &impl AsContextRef) -> JsValue { match self { Self::I32(i) => JsValue::from_f64(*i as f64), Self::I64(i) => JsValue::from_f64(*i as f64), Self::F32(f) => JsValue::from_f64(*f as f64), Self::F64(f) => JsValue::from_f64(*f), - Self::FuncRef(func) => func.as_ref().unwrap().exported.function.clone().into(), - v => unimplemented!( - "The value `{:?}` is not yet supported in the JS Function API", - v - ), + Self::FuncRef(Some(func)) => func + .handle + .get(ctx.as_context_ref().objects()) + .function + .clone() + .into(), + Self::FuncRef(None) => JsValue::null(), } } } diff --git a/lib/api/src/js/value.rs b/lib/api/src/js/value.rs new file mode 100644 index 00000000000..703b6df4502 --- /dev/null +++ b/lib/api/src/js/value.rs @@ -0,0 +1,423 @@ +use std::convert::TryFrom; +use std::fmt; +use std::string::{String, ToString}; + +use wasmer_types::Type; + +//use crate::ExternRef; +use crate::js::externals::function::Function; + +use super::context::AsContextRef; + +/// WebAssembly computations manipulate values of basic value types: +/// * Integers (32 or 64 bit width) +/// * Floating-point (32 or 64 bit width) +/// +/// Spec: +#[derive(Clone, PartialEq)] +pub enum Value { + /// A 32-bit integer. + /// + /// In Wasm integers are sign-agnostic, i.e. this can either be signed or unsigned. + I32(i32), + + /// A 64-bit integer. + /// + /// In Wasm integers are sign-agnostic, i.e. this can either be signed or unsigned. + I64(i64), + + /// A 32-bit float. + F32(f32), + + /// A 64-bit float. + F64(f64), + + /// An `externref` value which can hold opaque data to the wasm instance itself. + //ExternRef(Option), + + /// A first-class reference to a WebAssembly function. + FuncRef(Option), +} + +macro_rules! accessors { + ($bind:ident $(($variant:ident($ty:ty) $get:ident $unwrap:ident $cvt:expr))*) => ($( + /// Attempt to access the underlying value of this `Value`, returning + /// `None` if it is not the correct type. + pub fn $get(&self) -> Option<$ty> { + if let Self::$variant($bind) = self { + Some($cvt) + } else { + None + } + } + + /// Returns the underlying value of this `Value`, panicking if it's the + /// wrong type. + /// + /// # Panics + /// + /// Panics if `self` is not of the right type. + pub fn $unwrap(&self) -> $ty { + self.$get().expect(concat!("expected ", stringify!($ty))) + } + )*) +} + +impl Value { + /// Returns a null `externref` value. + pub fn null() -> Self { + Self::FuncRef(None) + } + + /// Returns the corresponding [`Type`] for this `Value`. + pub fn ty(&self) -> Type { + match self { + Self::I32(_) => Type::I32, + Self::I64(_) => Type::I64, + Self::F32(_) => Type::F32, + Self::F64(_) => Type::F64, + //Self::ExternRef(_) => Type::ExternRef, + Self::FuncRef(_) => Type::FuncRef, + } + } + + /// Converts the `Value` into a `f64`. + pub fn as_raw(&self, ctx: &impl AsContextRef) -> f64 { + match *self { + Self::I32(v) => v as f64, + Self::I64(v) => v as f64, + Self::F32(v) => v as f64, + Self::F64(v) => v, + Self::FuncRef(Some(ref f)) => f + .handle + .get(ctx.as_context_ref().objects()) + .function + .as_f64() + .unwrap_or(0_f64), //TODO is this correct? + + Self::FuncRef(None) => 0_f64, + //Self::ExternRef(Some(ref e)) => unsafe { *e.address().0 } as .into_raw(), + //Self::ExternRef(None) => externref: 0 }, + } + } + + /// Converts a `f64` to a `Value`. + /// + /// # Safety + /// + pub unsafe fn from_raw(_ctx: &impl AsContextRef, ty: Type, raw: f64) -> Self { + match ty { + Type::I32 => Self::I32(raw as i32), + Type::I64 => Self::I64(raw as i64), + Type::F32 => Self::F32(raw as f32), + Type::F64 => Self::F64(raw), + Type::FuncRef => todo!(), + Type::V128 => todo!(), + Type::ExternRef => todo!(), + //Self::ExternRef( + //{ + //VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(ctx, e)), + //), + } + } + + /// Checks whether a value can be used with the given context. + /// + /// Primitive (`i32`, `i64`, etc) and null funcref/externref values are not + /// tied to a context and can be freely shared between contexts. + /// + /// Externref and funcref values are tied to a context and can only be used + /// with that context. + pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + match self { + Self::I32(_) + | Self::I64(_) + | Self::F32(_) + | Self::F64(_) + //| Self::ExternRef(None) + | Self::FuncRef(None) => true, + //Self::ExternRef(Some(e)) => e.is_from_context(ctx), + Self::FuncRef(Some(f)) => f.is_from_context(ctx), + } + } + + accessors! { + e + (I32(i32) i32 unwrap_i32 *e) + (I64(i64) i64 unwrap_i64 *e) + (F32(f32) f32 unwrap_f32 *e) + (F64(f64) f64 unwrap_f64 *e) + //(ExternRef(&Option) externref unwrap_externref e) + (FuncRef(&Option) funcref unwrap_funcref e) + } +} + +impl fmt::Debug for Value { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::I32(v) => write!(f, "I32({:?})", v), + Self::I64(v) => write!(f, "I64({:?})", v), + Self::F32(v) => write!(f, "F32({:?})", v), + Self::F64(v) => write!(f, "F64({:?})", v), + //Self::ExternRef(None) => write!(f, "Null ExternRef"), + //Self::ExternRef(Some(v)) => write!(f, "ExternRef({:?})", v), + Self::FuncRef(None) => write!(f, "Null FuncRef"), + Self::FuncRef(Some(v)) => write!(f, "FuncRef({:?})", v), + } + } +} + +impl ToString for Value { + fn to_string(&self) -> String { + match self { + Self::I32(v) => v.to_string(), + Self::I64(v) => v.to_string(), + Self::F32(v) => v.to_string(), + Self::F64(v) => v.to_string(), + //Self::ExternRef(_) => "externref".to_string(), + Self::FuncRef(_) => "funcref".to_string(), + } + } +} + +impl From for Value { + fn from(val: i32) -> Self { + Self::I32(val) + } +} + +impl From for Value { + fn from(val: u32) -> Self { + // In Wasm integers are sign-agnostic, so i32 is basically a 4 byte storage we can use for signed or unsigned 32-bit integers. + Self::I32(val as i32) + } +} + +impl From for Value { + fn from(val: i64) -> Self { + Self::I64(val) + } +} + +impl From for Value { + fn from(val: u64) -> Self { + // In Wasm integers are sign-agnostic, so i64 is basically an 8 byte storage we can use for signed or unsigned 64-bit integers. + Self::I64(val as i64) + } +} + +impl From for Value { + fn from(val: f32) -> Self { + Self::F32(val) + } +} + +impl From for Value { + fn from(val: f64) -> Self { + Self::F64(val) + } +} + +impl From for Value { + fn from(val: Function) -> Self { + Self::FuncRef(Some(val)) + } +} + +impl From> for Value { + fn from(val: Option) -> Self { + Self::FuncRef(val) + } +} + +//impl From for Value { +// fn from(val: ExternRef) -> Self { +// Self::ExternRef(Some(val)) +// } +//} +// +//impl From> for Value { +// fn from(val: Option) -> Self { +// Self::ExternRef(val) +// } +//} + +const NOT_I32: &str = "Value is not of Wasm type i32"; +const NOT_I64: &str = "Value is not of Wasm type i64"; +const NOT_F32: &str = "Value is not of Wasm type f32"; +const NOT_F64: &str = "Value is not of Wasm type f64"; +const NOT_FUNCREF: &str = "Value is not of Wasm type funcref"; +//const NOT_EXTERNREF: &str = "Value is not of Wasm type externref"; + +impl TryFrom for i32 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i32().ok_or(NOT_I32) + } +} + +impl TryFrom for u32 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i32().ok_or(NOT_I32).map(|int| int as Self) + } +} + +impl TryFrom for i64 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i64().ok_or(NOT_I64) + } +} + +impl TryFrom for u64 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.i64().ok_or(NOT_I64).map(|int| int as Self) + } +} + +impl TryFrom for f32 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.f32().ok_or(NOT_F32) + } +} + +impl TryFrom for f64 { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + value.f64().ok_or(NOT_F64) + } +} + +impl TryFrom for Option { + type Error = &'static str; + + fn try_from(value: Value) -> Result { + match value { + Value::FuncRef(f) => Ok(f), + _ => Err(NOT_FUNCREF), + } + } +} + +//impl TryFrom for Option { +// type Error = &'static str; +// +// fn try_from(value: Value) -> Result { +// match value { +// Value::ExternRef(e) => Ok(e), +// _ => Err(NOT_EXTERNREF), +// } +// } +//} + +#[cfg(tests)] +mod tests { + use super::*; + /* + + fn test_value_i32_from_u32() { + let bytes = [0x00, 0x00, 0x00, 0x00]; + let v = Value::<()>::from(u32::from_be_bytes(bytes)); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); + + let bytes = [0x00, 0x00, 0x00, 0x01]; + let v = Value::<()>::from(u32::from_be_bytes(bytes)); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); + + let bytes = [0xAA, 0xBB, 0xCC, 0xDD]; + let v = Value::<()>::from(u32::from_be_bytes(bytes)); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); + + let bytes = [0xFF, 0xFF, 0xFF, 0xFF]; + let v = Value::<()>::from(u32::from_be_bytes(bytes)); + assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); + } + + fn test_value_i64_from_u64() { + let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let v = Value::<()>::from(u64::from_be_bytes(bytes)); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); + + let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]; + let v = Value::<()>::from(u64::from_be_bytes(bytes)); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); + + let bytes = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11]; + let v = Value::<()>::from(u64::from_be_bytes(bytes)); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); + + let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; + let v = Value::<()>::from(u64::from_be_bytes(bytes)); + assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); + } + + fn convert_value_to_i32() { + let value = Value::<()>::I32(5678); + let result = i32::try_from(value); + assert_eq!(result.unwrap(), 5678); + + let value = Value::<()>::from(u32::MAX); + let result = i32::try_from(value); + assert_eq!(result.unwrap(), -1); + } + + fn convert_value_to_u32() { + let value = Value::<()>::from(u32::MAX); + let result = u32::try_from(value); + assert_eq!(result.unwrap(), u32::MAX); + + let value = Value::<()>::I32(-1); + let result = u32::try_from(value); + assert_eq!(result.unwrap(), u32::MAX); + } + + fn convert_value_to_i64() { + let value = Value::<()>::I64(5678); + let result = i64::try_from(value); + assert_eq!(result.unwrap(), 5678); + + let value = Value::<()>::from(u64::MAX); + let result = i64::try_from(value); + assert_eq!(result.unwrap(), -1); + } + + fn convert_value_to_u64() { + let value = Value::<()>::from(u64::MAX); + let result = u64::try_from(value); + assert_eq!(result.unwrap(), u64::MAX); + + let value = Value::<()>::I64(-1); + let result = u64::try_from(value); + assert_eq!(result.unwrap(), u64::MAX); + } + + fn convert_value_to_f32() { + let value = Value::<()>::F32(1.234); + let result = f32::try_from(value); + assert_eq!(result.unwrap(), 1.234); + + let value = Value::<()>::F64(1.234); + let result = f32::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type f32"); + } + + fn convert_value_to_f64() { + let value = Value::<()>::F64(1.234); + let result = f64::try_from(value); + assert_eq!(result.unwrap(), 1.234); + + let value = Value::<()>::F32(1.234); + let result = f64::try_from(value); + assert_eq!(result.unwrap_err(), "Value is not of Wasm type f64"); + } + */ +} diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index 6fdbb99f555..9bf0520290f 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -26,7 +26,6 @@ ) )] #![cfg_attr(feature = "js", crate_type = "cdylib")] -#![cfg_attr(feature = "js", crate_type = "rlib")] //! [`Wasmer`](https://wasmer.io/) is the most popular //! [WebAssembly](https://webassembly.org/) runtime for Rust. It supports diff --git a/lib/api/src/sys/context.rs b/lib/api/src/sys/context.rs index d72e68499db..4289b818647 100644 --- a/lib/api/src/sys/context.rs +++ b/lib/api/src/sys/context.rs @@ -27,7 +27,7 @@ pub(crate) struct ContextInner { /// The `T` generic parameter allows arbitrary data to be attached to a context. /// This data can be accessed using the [`Context::data`] and /// [`Context::data_mut`] methods. Host functions defined using -/// [`Function::new_with_env`] and [`Function::new_native_with_env`] receive +/// [`Function::new`] and [`Function::new_native`] receive /// a reference to the context when they are called. pub struct Context { pub(crate) inner: Box>, diff --git a/lib/api/src/sys/exports.rs b/lib/api/src/sys/exports.rs index 85381bc216d..dd595d540f6 100644 --- a/lib/api/src/sys/exports.rs +++ b/lib/api/src/sys/exports.rs @@ -180,7 +180,7 @@ impl Exports { } /// Like `get_with_generics` but with a WeakReference to the `InstanceRef` internally. - /// This is useful for passing data into `WasmerEnv`, for example. + /// This is useful for passing data into Context data, for example. pub fn get_with_generics_weak<'a, T, Args, Rets>(&'a self, name: &str) -> Result where Args: WasmTypeList, diff --git a/lib/api/tests/js_externals.rs b/lib/api/tests/js_externals.rs index d46104faede..187e6a6b1fe 100644 --- a/lib/api/tests/js_externals.rs +++ b/lib/api/tests/js_externals.rs @@ -6,18 +6,19 @@ mod js { #[wasm_bindgen_test] fn global_new() { let store = Store::default(); - let global = Global::new(&store, Value::I32(10)); + let mut ctx = Context::new(&store, ()); + let global = Global::new(&mut ctx, Value::I32(10)); assert_eq!( - *global.ty(), + global.ty(&ctx), GlobalType { ty: Type::I32, mutability: Mutability::Const } ); - let global_mut = Global::new_mut(&store, Value::I32(10)); + let global_mut = Global::new_mut(&mut ctx, Value::I32(10)); assert_eq!( - *global_mut.ty(), + global_mut.ty(&ctx), GlobalType { ty: Type::I32, mutability: Mutability::Var @@ -28,15 +29,16 @@ mod js { #[wasm_bindgen_test] fn global_get() { let store = Store::default(); - let global_i32 = Global::new(&store, Value::I32(10)); - assert_eq!(global_i32.get(), Value::I32(10)); + let mut ctx = Context::new(&store, ()); + let global_i32 = Global::new(&mut ctx, Value::I32(10)); + assert_eq!(global_i32.get(&ctx), Value::I32(10)); // 64-bit values are not yet fully supported in some versions of Node // Commenting this tests for now: // let global_i64 = Global::new(&store, Value::I64(20)); // assert_eq!(global_i64.get(), Value::I64(20)); - let global_f32 = Global::new(&store, Value::F32(10.0)); - assert_eq!(global_f32.get(), Value::F32(10.0)); + let global_f32 = Global::new(&mut ctx, Value::F32(10.0)); + assert_eq!(global_f32.get(&ctx), Value::F32(10.0)); // let global_f64 = Global::new(&store, Value::F64(20.0)); // assert_eq!(global_f64.get(), Value::F64(20.0)); } @@ -44,30 +46,32 @@ mod js { #[wasm_bindgen_test] fn global_set() { let store = Store::default(); - let global_i32 = Global::new(&store, Value::I32(10)); + let mut ctx = Context::new(&store, ()); + let global_i32 = Global::new(&mut ctx, Value::I32(10)); // Set on a constant should error - assert!(global_i32.set(Value::I32(20)).is_err()); + assert!(global_i32.set(&mut ctx, Value::I32(20)).is_err()); - let global_i32_mut = Global::new_mut(&store, Value::I32(10)); + let global_i32_mut = Global::new_mut(&mut ctx, Value::I32(10)); // Set on different type should error - assert!(global_i32_mut.set(Value::I64(20)).is_err()); + assert!(global_i32_mut.set(&mut ctx, Value::I64(20)).is_err()); // Set on same type should succeed - global_i32_mut.set(Value::I32(20)).unwrap(); - assert_eq!(global_i32_mut.get(), Value::I32(20)); + global_i32_mut.set(&mut ctx, Value::I32(20)).unwrap(); + assert_eq!(global_i32_mut.get(&ctx), Value::I32(20)); } #[wasm_bindgen_test] fn table_new() { let store = Store::default(); + let mut ctx = Context::new(&store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: None, }; - let f = Function::new_native(&store, || {}); - let table = Table::new(&store, table_type, Value::FuncRef(Some(f))).unwrap(); - assert_eq!(*table.ty(), table_type); + let f = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>| {}); + let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f))).unwrap(); + assert_eq!(table.ty(&ctx), table_type); // table.get() // Anyrefs not yet supported @@ -77,7 +81,7 @@ mod js { // maximum: None, // }; // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; - // assert_eq!(*table.ty(), table_type); + // assert_eq!(*table.ty(&ctx), table_type); } // Tables are not yet fully supported in Wasm @@ -87,14 +91,15 @@ mod js { // #[ignore] // fn table_get() -> Result<()> { // let store = Store::default(); + // let mut ctx = Context::new(&store, ()); // let table_type = TableType { // ty: Type::FuncRef, // minimum: 0, // maximum: Some(1), // }; - // let f = Function::new_native(&store, |num: i32| num + 1); + // let f = Function::new(&mut ctx, |num: i32| num + 1); // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; - // assert_eq!(*table.ty(), table_type); + // assert_eq!(*table.ty(&ctx), table_type); // let _elem = table.get(0).unwrap(); // // assert_eq!(elem.funcref().unwrap(), f); // Ok(()) @@ -110,12 +115,13 @@ mod js { // #[test] // fn table_grow() -> Result<()> { // let store = Store::default(); + // let mut ctx = Context::new(&store, ()); // let table_type = TableType { // ty: Type::FuncRef, // minimum: 0, // maximum: Some(10), // }; - // let f = Function::new_native(&store, |num: i32| num + 1); + // let f = Function::new(&mut ctx, |num: i32| num + 1); // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; // // Growing to a bigger maximum should return None // let old_len = table.grow(12, Value::FuncRef(Some(f.clone()))); @@ -138,29 +144,31 @@ mod js { #[wasm_bindgen_test] fn memory_new() { let store = Store::default(); + let mut ctx = Context::new(&store, ()); let memory_type = MemoryType { shared: false, minimum: Pages(0), maximum: Some(Pages(10)), }; - let memory = Memory::new(&store, memory_type).unwrap(); - assert_eq!(memory.size(), Pages(0)); - assert_eq!(memory.ty(), memory_type); + let memory = Memory::new(&mut ctx, memory_type).unwrap(); + assert_eq!(memory.size(&ctx), Pages(0)); + assert_eq!(memory.ty(&ctx), memory_type); } #[wasm_bindgen_test] fn memory_grow() { let store = Store::default(); + let mut ctx = Context::new(&store, ()); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&store, desc).unwrap(); - assert_eq!(memory.size(), Pages(10)); + let memory = Memory::new(&mut ctx, desc).unwrap(); + assert_eq!(memory.size(&ctx), Pages(10)); - let result = memory.grow(Pages(2)).unwrap(); + let result = memory.grow(&mut ctx, Pages(2)).unwrap(); assert_eq!(result, Pages(10)); - assert_eq!(memory.size(), Pages(12)); + assert_eq!(memory.size(&ctx), Pages(12)); - let result = memory.grow(Pages(10)); + let result = memory.grow(&mut ctx, Pages(10)); assert!(result.is_err()); assert_eq!( result, @@ -174,27 +182,33 @@ mod js { #[wasm_bindgen_test] fn function_new() { let store = Store::default(); - let function = Function::new_native(&store, || {}); - assert_eq!(function.ty().clone(), FunctionType::new(vec![], vec![])); - let function = Function::new_native(&store, |_a: i32| {}); + let mut ctx = Context::new(&store, ()); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<'_, ()>| {}); + assert_eq!(function.ty(&ctx).clone(), FunctionType::new(vec![], vec![])); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<'_, ()>, _a: i32| {}); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![Type::I32], vec![]) ); - let function = Function::new_native(&store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); + let function = Function::new_native( + &mut ctx, + |_ctx: ContextMut<'_, ()>, _a: i32, _b: i64, _c: f32, _d: f64| {}, + ); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = Function::new_native(&store, || -> i32 { 1 }); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<'_, ()>| -> i32 { 1 }); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![], vec![Type::I32]) ); - let function = - Function::new_native(&store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); + let function = Function::new_native( + &mut ctx, + |_ctx: ContextMut<'_, ()>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + ); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); } @@ -202,40 +216,38 @@ mod js { #[wasm_bindgen_test] fn function_new_env() { let store = Store::default(); - #[derive(Clone, WasmerEnv)] + #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; - let function = Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv| {}); - assert_eq!(function.ty().clone(), FunctionType::new(vec![], vec![])); - let function = - Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv, _a: i32| {}); + let mut ctx = Context::new(&store, my_env); + + let function = Function::new_native(&mut ctx, |_: ContextMut<'_, MyEnv>| {}); + assert_eq!(function.ty(&ctx).clone(), FunctionType::new(vec![], vec![])); + let function = Function::new_native(&mut ctx, |_: ContextMut<'_, MyEnv>, _a: i32| {}); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![Type::I32], vec![]) ); - let function = Function::new_native_with_env( - &store, - my_env.clone(), - |_env: &MyEnv, _a: i32, _b: i64, _c: f32, _d: f64| {}, + let function = Function::new_native( + &mut ctx, + |_: ContextMut<'_, MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {}, ); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = - Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv| -> i32 { 1 }); + let function = Function::new_native(&mut ctx, |_: ContextMut<'_, MyEnv>| -> i32 { 1 }); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![], vec![Type::I32]) ); - let function = Function::new_native_with_env( - &store, - my_env.clone(), - |_env: &MyEnv| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + let function = Function::new_native( + &mut ctx, + |_: ContextMut<'_, MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, ); assert_eq!( - function.ty().clone(), + function.ty(&ctx).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); } @@ -243,183 +255,185 @@ mod js { #[wasm_bindgen_test] fn function_new_dynamic() { let store = Store::default(); + let mut ctx = Context::new(&store, ()); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&ctx).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new(&store, function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().params(), [Type::V128]); - assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]); + let function = Function::new( + &mut ctx, + function_type, + |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&ctx).params(), [Type::V128]); + assert_eq!( + function.ty(&ctx).results(), + [Type::I32, Type::F32, Type::F64] + ); } #[wasm_bindgen_test] fn function_new_dynamic_env() { let store = Store::default(); - #[derive(Clone, WasmerEnv)] + #[derive(Clone)] struct MyEnv {} + let my_env = MyEnv {}; + let mut ctx = Context::new(&store, my_env); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new_with_env( - &store, + let function = Function::new( + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new_with_env( - &store, + let function = Function::new( + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new_with_env( - &store, + let function = Function::new( + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new_with_env( - &store, + let function = Function::new( + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new_with_env( - &store, + let function = Function::new( + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&ctx).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new_with_env( - &store, + let function = Function::new( + &mut ctx, function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&ctx).params(), [Type::V128]); + assert_eq!( + function.ty(&ctx).results(), + [Type::I32, Type::F32, Type::F64] ); - assert_eq!(function.ty().params(), [Type::V128]); - assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]); } #[wasm_bindgen_test] fn native_function_works() { let store = Store::default(); - let function = Function::new_native(&store, || {}); - let typed_function: TypedFunction<(), ()> = function.native().unwrap(); - let result = typed_function.call(); + let mut ctx = Context::new(&store, ()); + let function = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>| {}); + let typed_function: TypedFunction<(), ()> = function.native(&mut ctx).unwrap(); + let result = typed_function.call(&mut ctx); assert!(result.is_ok()); - let function = Function::new_native(&store, |a: i32| -> i32 { a + 1 }); - let typed_function: TypedFunction = function.native().unwrap(); - assert_eq!(typed_function.call(3).unwrap(), 4); + let function = + Function::new_native(&mut ctx, |_: ContextMut<'_, ()>, a: i32| -> i32 { a + 1 }); + let typed_function: TypedFunction = function.native(&mut ctx).unwrap(); + assert_eq!(typed_function.call(&mut ctx, 3).unwrap(), 4); // fn rust_abi(a: i32, b: i64, c: f32, d: f64) -> u64 { // (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) // } - // let function = Function::new_native(&store, rust_abi); - // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = function.native().unwrap(); + // let function = Function::new(&mut ctx, rust_abi); + // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = function.native(&mut ctx).unwrap(); // assert_eq!(typed_function.call(8, 4, 1.5, 5.).unwrap(), 8415); - let function = Function::new_native(&store, || -> i32 { 1 }); - let typed_function: TypedFunction<(), i32> = function.native().unwrap(); - assert_eq!(typed_function.call().unwrap(), 1); + let function = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>| -> i32 { 1 }); + let typed_function: TypedFunction<(), i32> = function.native(&mut ctx).unwrap(); + assert_eq!(typed_function.call(&mut ctx).unwrap(), 1); - let function = Function::new_native(&store, |_a: i32| {}); - let typed_function: TypedFunction = function.native().unwrap(); - assert!(typed_function.call(4).is_ok()); + let function = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>, _a: i32| {}); + let typed_function: TypedFunction = function.native(&mut ctx).unwrap(); + assert!(typed_function.call(&mut ctx, 4).is_ok()); - // let function = Function::new_native(&store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = function.native().unwrap(); + // let function = Function::new(&mut ctx, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); + // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = function.native(&mut ctx).unwrap(); // assert_eq!(typed_function.call().unwrap(), (1, 2, 3.0, 4.0)); } #[wasm_bindgen_test] fn function_outlives_instance() { let store = Store::default(); + let mut ctx = Context::new(&store, ()); let wat = r#"(module - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export "sum" (func $sum_f))) -"#; + (type $sum_t (func (param i32 i32) (result i32))) + (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) + local.get $x + local.get $y + i32.add) + (export "sum" (func $sum_f))) + "#; let f = { let module = Module::new(&store, wat).unwrap(); - let instance = Instance::new(&module, &imports! {}).unwrap(); + let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); let f = instance.exports.get_function("sum").unwrap(); assert_eq!( - f.call(&[Val::I32(4), Val::I32(5)]).unwrap(), + f.call(&mut ctx, &[Val::I32(4), Val::I32(5)]).unwrap(), vec![Val::I32(9)].into_boxed_slice() ); f.clone() }; assert_eq!( - f.call(&[Val::I32(4), Val::I32(5)]).unwrap(), + f.call(&mut ctx, &[Val::I32(4), Val::I32(5)]).unwrap(), vec![Val::I32(9)].into_boxed_slice() ); } - - #[wasm_bindgen_test] - fn manually_generate_wasmer_env() { - let store = Store::default(); - #[derive(WasmerEnv, Clone)] - struct MyEnv { - val: u32, - memory: LazyInit, - } - - fn host_function(env: &mut MyEnv, arg1: u32, arg2: u32) -> u32 { - env.val + arg1 + arg2 - } - - let mut env = MyEnv { - val: 5, - memory: LazyInit::new(), - }; - - let result = host_function(&mut env, 7, 9); - assert_eq!(result, 21); - - let memory = Memory::new(&store, MemoryType::new(0, None, false)).unwrap(); - env.memory.initialize(memory); - - let result = host_function(&mut env, 1, 2); - assert_eq!(result, 8); - } } diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs index 00a4bc5666d..c64d2e45431 100644 --- a/lib/api/tests/js_instance.rs +++ b/lib/api/tests/js_instance.rs @@ -4,16 +4,33 @@ mod js { use wasm_bindgen_test::*; use wasmer::*; + /* + * For debugging, put web_sys in dev dependencies in Cargo.toml with the "console" feature + * on. + * + extern crate web_sys; + + // A macro to provide `println!(..)`-style syntax for `console.log` logging. + macro_rules! log { + ( $( $t:tt )* ) => { + web_sys::console::log_1(&format!( $( $t )* ).into()); + } + } + */ + macro_rules! log { + ( $( $t:tt )* ) => {}; + } + #[wasm_bindgen_test] fn test_exported_memory() { let store = Store::default(); let mut module = Module::new( &store, br#" - (module - (memory (export "mem") 1) - ) - "#, + (module + (memory (export "mem") 1) + ) + "#, ) .unwrap(); module @@ -24,17 +41,19 @@ mod js { .unwrap(); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object).unwrap(); + let mut ctx = Context::new(&store, ()); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("mem").unwrap(); - assert_eq!(memory.ty(), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.size(), Pages(1)); - assert_eq!(memory.data_size(), 65536); - - memory.grow(Pages(1)).unwrap(); - assert_eq!(memory.ty(), MemoryType::new(Pages(2), None, false)); - assert_eq!(memory.size(), Pages(2)); - assert_eq!(memory.data_size(), 65536 * 2); + assert!(memory.is_from_context(&ctx)); + assert_eq!(memory.ty(&ctx), MemoryType::new(Pages(1), None, false)); + assert_eq!(memory.size(&ctx), Pages(1)); + assert_eq!(memory.data_size(&ctx), 65536); + + memory.grow(&mut ctx, Pages(1)).unwrap(); + assert_eq!(memory.ty(&ctx), MemoryType::new(Pages(1), None, false)); + assert_eq!(memory.size(&ctx), Pages(2)); + assert_eq!(memory.data_size(&ctx), 65536 * 2); } #[wasm_bindgen_test] @@ -43,12 +62,12 @@ mod js { let mut module = Module::new( &store, br#" - (module - (func (export "get_magic") (result i32) - (i32.const 42) + (module + (func (export "get_magic") (result i32) + (i32.const 42) + ) ) - ) - "#, + "#, ) .unwrap(); module @@ -62,16 +81,17 @@ mod js { .unwrap(); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object).unwrap(); + let mut ctx = Context::new(&store, ()); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let get_magic = instance.exports.get_function("get_magic").unwrap(); assert_eq!( - get_magic.ty().clone(), + get_magic.ty(&ctx).clone(), FunctionType::new(vec![], vec![Type::I32]) ); let expected = vec![Val::I32(42)].into_boxed_slice(); - assert_eq!(get_magic.call(&[]), Ok(expected)); + assert_eq!(get_magic.call(&mut ctx, &[]).unwrap(), expected); } #[wasm_bindgen_test] @@ -80,13 +100,13 @@ mod js { let mut module = Module::new( &store, br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) + (module + (func $imported (import "env" "imported") (param i32) (result i32)) + (func (export "exported") (param i32) (result i32) + (call $imported (local.get 0)) + ) ) - ) - "#, + "#, ) .unwrap(); module @@ -101,12 +121,14 @@ mod js { ))], }) .unwrap(); + let mut ctx = Context::new(&store, ()); let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new(&store, imported_signature, |args| { - println!("Calling `imported`..."); + + let imported = Function::new(&mut ctx, imported_signature, |_env, args| { + log!("Calling `imported`..."); let result = args[0].unwrap_i32() * 2; - println!("Result of `imported`: {:?}", result); + log!("Result of `imported`: {:?}", result); Ok(vec![Value::I32(result)]) }); @@ -115,12 +137,12 @@ mod js { "imported" => imported, } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(6)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(3)]), Ok(expected)); + assert_eq!(exported.call(&mut ctx, &[Val::I32(3)]).unwrap(), expected); } // We comment it for now because in old versions of Node, only single return values are supported @@ -158,9 +180,9 @@ mod js { // let multivalue_signature = // FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]); // let multivalue = Function::new(&store, &multivalue_signature, |args| { - // println!("Calling `imported`..."); + // log!("Calling `imported`..."); // // let result = args[0].unwrap_i32() * ; - // // println!("Result of `imported`: {:?}", result); + // // log!("Result of `imported`: {:?}", result); // Ok(vec![args[1].clone(), args[0].clone()]) // }); @@ -189,13 +211,13 @@ mod js { let mut module = Module::new( &store, br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) + (module + (func $imported (import "env" "imported") (param i32) (result i32)) + (func (export "exported") (param i32) (result i32) + (call $imported (local.get 0)) + ) ) - ) - "#, + "#, ) .unwrap(); module @@ -211,35 +233,32 @@ mod js { }) .unwrap(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env { multiplier: i32, } + let mut ctx = Context::new(&store, Env { multiplier: 3 }); + let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env( - &store, - &imported_signature, - Env { multiplier: 3 }, - |env, args| { - println!("Calling `imported`..."); - let result = args[0].unwrap_i32() * env.multiplier; - println!("Result of `imported`: {:?}", result); - Ok(vec![Value::I32(result)]) - }, - ); + let imported = Function::new(&mut ctx, &imported_signature, |ctx, args| { + log!("Calling `imported`..."); + let result = args[0].unwrap_i32() * ctx.data().multiplier; + log!("Result of `imported`: {:?}", result); + Ok(vec![Value::I32(result)]) + }); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(9)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(3)]), Ok(expected)); + assert_eq!(exported.call(&mut ctx, &[Val::I32(3)]), Ok(expected)); } #[wasm_bindgen_test] @@ -248,13 +267,13 @@ mod js { let mut module = Module::new( &store, br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) + (module + (func $imported (import "env" "imported") (param i32) (result i32)) + (func (export "exported") (param i32) (result i32) + (call $imported (local.get 0)) + ) ) - ) - "#, + "#, ) .unwrap(); module @@ -270,23 +289,24 @@ mod js { }) .unwrap(); - fn imported_fn(arg: u32) -> u32 { + fn imported_fn(_: ContextMut<'_, ()>, arg: u32) -> u32 { return arg + 1; } - let imported = Function::new_native(&store, imported_fn); + let mut ctx = Context::new(&store, ()); + let imported = Function::new_native(&mut ctx, imported_fn); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(5)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] @@ -295,13 +315,13 @@ mod js { let mut module = Module::new( &store, br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) + (module + (func $imported (import "env" "imported") (param i32) (result i32)) + (func (export "exported") (param i32) (result i32) + (call $imported (local.get 0)) + ) ) - ) - "#, + "#, ) .unwrap(); module @@ -317,28 +337,33 @@ mod js { }) .unwrap(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone, Debug)] struct Env { multiplier: u32, } - fn imported_fn(env: &Env, arg: u32) -> u32 { - return env.multiplier * arg; + fn imported_fn(ctx: ContextMut<'_, Env>, arg: u32) -> u32 { + log!("inside imported_fn: ctx.data is {:?}", ctx.data()); + // log!("inside call id is {:?}", ctx.as_context_ref().objects().id); + return ctx.data().multiplier * arg; } - let imported = Function::new_native_with_env(&store, Env { multiplier: 3 }, imported_fn); + let mut ctx = Context::new(&store, Env { multiplier: 3 }); + + let imported = Function::new_native(&mut ctx, imported_fn); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(12)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected)); + ctx.data_mut().multiplier = 3; + assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] @@ -347,14 +372,14 @@ mod js { let mut module = Module::new( &store, br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) + (module + (func $imported (import "env" "imported") (param i32) (result i32)) + (func (export "exported") (param i32) (result i32) + (call $imported (local.get 0)) + ) + (memory (export "memory") 1) ) - (memory (export "memory") 1) - ) - "#, + "#, ) .unwrap(); module @@ -370,79 +395,77 @@ mod js { }) .unwrap(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone, Debug)] struct Env { multiplier: u32, - #[wasmer(export)] - memory: LazyInit, + memory: Option, } - fn imported_fn(env: &Env, arg: u32) -> u32 { - let memory = env.memory_ref().unwrap(); - let memory_val = memory.uint8view().get_index(0); - return (memory_val as u32) * env.multiplier * arg; + fn imported_fn(ctx: ContextMut<'_, Env>, arg: u32) -> u32 { + let memory: &Memory = ctx.data().memory.as_ref().unwrap(); + let memory_val = memory.uint8view(&ctx).get_index(0); + return (memory_val as u32) * ctx.data().multiplier * arg; } - let imported = Function::new_native_with_env( + let mut ctx = Context::new( &store, Env { multiplier: 3, - memory: LazyInit::new(), + memory: None, }, - imported_fn, ); + let imported = Function::new_native(&mut ctx, imported_fn); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.data_size(), 65536); - let memory_val = memory.uint8view().get_index(0); + assert_eq!(memory.data_size(&ctx), 65536); + let memory_val = memory.uint8view(&ctx).get_index(0); assert_eq!(memory_val, 0); - memory.uint8view().set_index(0, 2); - let memory_val = memory.uint8view().get_index(0); + memory.uint8view(&ctx).set_index(0, 2); + let memory_val = memory.uint8view(&ctx).get_index(0); assert_eq!(memory_val, 2); + ctx.data_mut().memory = Some(memory.clone()); + let exported = instance.exports.get_function("exported").unwrap(); // It works with the provided memory let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.uint8view().set_index(0, 3); + memory.uint8view(&ctx).set_index(0, 3); let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] fn test_unit_native_function_env() { let store = Store::default(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env { multiplier: u32, } - fn imported_fn(env: &Env, args: &[Val]) -> Result, RuntimeError> { - let value = env.multiplier * args[0].unwrap_i32() as u32; + let mut ctx = Context::new(&store, Env { multiplier: 3 }); + + fn imported_fn(ctx: ContextMut<'_, Env>, args: &[Val]) -> Result, RuntimeError> { + let value = ctx.data().multiplier * args[0].unwrap_i32() as u32; return Ok(vec![Val::I32(value as _)]); } let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env( - &store, - imported_signature, - Env { multiplier: 3 }, - imported_fn, - ); + let imported = Function::new(&mut ctx, imported_signature, imported_fn); let expected = vec![Val::I32(12)].into_boxed_slice(); - assert_eq!(imported.call(&[Val::I32(4)]), Ok(expected)); + assert_eq!(imported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] @@ -451,14 +474,14 @@ mod js { let mut module = Module::new( &store, br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) + (module + (func $imported (import "env" "imported") (param i32) (result i32)) + (func (export "exported") (param i32) (result i32) + (call $imported (local.get 0)) + ) + (memory (export "memory") 1) ) - (memory (export "memory") 1) - ) - "#, + "#, ) .unwrap(); module @@ -474,57 +497,58 @@ mod js { }) .unwrap(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone, Debug)] struct Env { multiplier: u32, - #[wasmer(export)] - memory: LazyInit, + memory: Option, } - fn imported_fn(env: &Env, args: &[Val]) -> Result, RuntimeError> { - let memory = env.memory_ref().unwrap(); - let memory_val = memory.uint8view().get_index(0); - let value = (memory_val as u32) * env.multiplier * args[0].unwrap_i32() as u32; + fn imported_fn(ctx: ContextMut<'_, Env>, args: &[Val]) -> Result, RuntimeError> { + let memory: &Memory = ctx.data().memory.as_ref().unwrap(); + let memory_val = memory.uint8view(&ctx).get_index(0); + let value = (memory_val as u32) * ctx.data().multiplier * args[0].unwrap_i32() as u32; return Ok(vec![Val::I32(value as _)]); } - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env( + let mut ctx = Context::new( &store, - imported_signature, Env { multiplier: 3, - memory: LazyInit::new(), + memory: None, }, - imported_fn, ); + let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); + let imported = Function::new(&mut ctx, imported_signature, imported_fn); + let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.data_size(), 65536); - let memory_val = memory.uint8view().get_index(0); + assert_eq!(memory.data_size(&ctx), 65536); + let memory_val = memory.uint8view(&ctx).get_index(0); assert_eq!(memory_val, 0); - memory.uint8view().set_index(0, 2); - let memory_val = memory.uint8view().get_index(0); + memory.uint8view(&ctx).set_index(0, 2); + let memory_val = memory.uint8view(&ctx).get_index(0); assert_eq!(memory_val, 2); + ctx.data_mut().memory = Some(memory.clone()); + let exported = instance.exports.get_function("exported").unwrap(); // It works with the provided memory let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.uint8view().set_index(0, 3); + memory.uint8view(&ctx).set_index(0, 3); let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] @@ -533,14 +557,14 @@ mod js { let mut module = Module::new( &store, br#" - (module - (global $mut_i32_import (import "" "global") (mut i32)) - (func (export "getGlobal") (result i32) (global.get $mut_i32_import)) - (func (export "incGlobal") (global.set $mut_i32_import ( - i32.add (i32.const 1) (global.get $mut_i32_import) - ))) - ) - "#, + (module + (global $mut_i32_import (import "" "global") (mut i32)) + (func (export "getGlobal") (result i32) (global.get $mut_i32_import)) + (func (export "incGlobal") (global.set $mut_i32_import ( + i32.add (i32.const 1) (global.get $mut_i32_import) + ))) + ) + "#, ) .unwrap(); module @@ -555,33 +579,34 @@ mod js { ], }) .unwrap(); - let global = Global::new_mut(&store, Value::I32(0)); + let mut ctx = Context::new(&store, ()); + let global = Global::new_mut(&mut ctx, Value::I32(0)); let import_object = imports! { "" => { "global" => global.clone() } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let get_global = instance.exports.get_function("getGlobal").unwrap(); assert_eq!( - get_global.call(&[]), + get_global.call(&mut ctx, &[]), Ok(vec![Val::I32(0)].into_boxed_slice()) ); - global.set(Value::I32(42)).unwrap(); + global.set(&mut ctx, Value::I32(42)).unwrap(); assert_eq!( - get_global.call(&[]), + get_global.call(&mut ctx, &[]), Ok(vec![Val::I32(42)].into_boxed_slice()) ); let inc_global = instance.exports.get_function("incGlobal").unwrap(); - inc_global.call(&[]).unwrap(); + inc_global.call(&mut ctx, &[]).unwrap(); assert_eq!( - get_global.call(&[]), + get_global.call(&mut ctx, &[]), Ok(vec![Val::I32(43)].into_boxed_slice()) ); - assert_eq!(global.get(), Val::I32(43)); + assert_eq!(global.get(&ctx), Val::I32(43)); } #[wasm_bindgen_test] @@ -590,28 +615,33 @@ mod js { let module = Module::new( &store, br#"(module - (func $add (import "env" "sum") (param i32 i32) (result i32)) - (func (export "add_one") (param i32) (result i32) - (call $add (local.get 0) (i32.const 1)) - ) - )"#, + (func $add (import "env" "sum") (param i32 i32) (result i32)) + (func (export "add_one") (param i32) (result i32) + (call $add (local.get 0) (i32.const 1)) + ) + )"#, ) .unwrap(); - fn sum(a: i32, b: i32) -> i32 { + fn sum(_: ContextMut<'_, ()>, a: i32, b: i32) -> i32 { a + b } + let mut ctx = Context::new(&store, ()); + let import_object = imports! { "env" => { - "sum" => Function::new_native(&store, sum), + "sum" => Function::new_native(&mut ctx, sum), } }; - let instance = Instance::new(&module, &import_object).unwrap(); - let add_one: TypedFunction = - instance.exports.get_typed_function("add_one").unwrap(); - assert_eq!(add_one.call(1), Ok(2)); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + + let add_one: TypedFunction = instance + .exports + .get_typed_function(&ctx, "add_one") + .unwrap(); + assert_eq!(add_one.call(&mut ctx, 1), Ok(2)); } #[wasm_bindgen_test] @@ -620,39 +650,45 @@ mod js { let module = Module::new( &store, br#" -(module - (type $run_t (func (param i32 i32) (result i32))) - (type $early_exit_t (func (param) (result))) - (import "env" "early_exit" (func $early_exit (type $early_exit_t))) - (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) - (call $early_exit) - (i32.add - local.get $x - local.get $y)) - (export "run" (func $run))) -"#, + (module + (type $run_t (func (param i32 i32) (result i32))) + (type $early_exit_t (func (param) (result))) + (import "env" "early_exit" (func $early_exit (type $early_exit_t))) + (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) + (call $early_exit) + (i32.add + local.get $x + local.get $y)) + (export "run" (func $run))) + "#, ) .unwrap(); - fn early_exit() { + fn early_exit(_: ContextMut<'_, ()>) { panic!("Do panic") } + let mut ctx = Context::new(&store, ()); let import_object = imports! { "env" => { - "early_exit" => Function::new_native(&store, early_exit), + "early_exit" => Function::new_native(&mut ctx, early_exit), } }; - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); let run_func: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function("run").unwrap(); + instance.exports.get_typed_function(&ctx, "run").unwrap(); - assert!(run_func.call(1, 7).is_err(), "Expected early termination",); + assert!( + run_func.call(&mut ctx, 1, 7).is_err(), + "Expected early termination", + ); let run_func = instance.exports.get_function("run").unwrap(); assert!( - run_func.call(&[Val::I32(1), Val::I32(7)]).is_err(), + run_func + .call(&mut ctx, &[Val::I32(1), Val::I32(7)]) + .is_err(), "Expected early termination", ); } @@ -663,20 +699,22 @@ mod js { let module = Module::new( &store, br#" -(module - (type $run_t (func (param i32 i32) (result i32))) - (type $early_exit_t (func (param) (result))) - (import "env" "early_exit" (func $early_exit (type $early_exit_t))) - (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) - (call $early_exit) - (i32.add - local.get $x - local.get $y)) - (export "run" (func $run))) -"#, + (module + (type $run_t (func (param i32 i32) (result i32))) + (type $early_exit_t (func (param) (result))) + (import "env" "early_exit" (func $early_exit (type $early_exit_t))) + (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) + (call $early_exit) + (i32.add + local.get $x + local.get $y)) + (export "run" (func $run))) + "#, ) .unwrap(); + let mut ctx = Context::new(&store, ()); + use std::fmt; #[derive(Debug, Clone, Copy)] @@ -690,16 +728,17 @@ mod js { impl std::error::Error for ExitCode {} - fn early_exit() -> Result<(), ExitCode> { + fn early_exit(_: ContextMut<'_, ()>) -> Result<(), ExitCode> { Err(ExitCode(1)) } let import_object = imports! { "env" => { - "early_exit" => Function::new_native(&store, early_exit), + "early_exit" => Function::new_native(&mut ctx, early_exit), } }; - let instance = Instance::new(&module, &import_object).unwrap(); + + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); fn test_result(result: Result) { match result { @@ -725,11 +764,11 @@ mod js { } let run_func: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function("run").unwrap(); - test_result(run_func.call(1, 7)); + instance.exports.get_typed_function(&ctx, "run").unwrap(); + test_result(run_func.call(&mut ctx, 1, 7)); let run_func = instance.exports.get_function("run").unwrap(); - test_result(run_func.call(&[Val::I32(1), Val::I32(7)])); + test_result(run_func.call(&mut ctx, &[Val::I32(1), Val::I32(7)])); } #[wasm_bindgen_test] @@ -753,7 +792,8 @@ mod js { .unwrap(); let import_object = imports! {}; - let result = Instance::new(&module, &import_object); + let mut ctx = Context::new(&store, ()); + let result = Instance::new(&mut ctx, &module, &import_object); let err = result.unwrap_err(); assert!(format!("{:?}", err).contains("zero")) } diff --git a/lib/api/tests/sys_export.rs b/lib/api/tests/sys_export.rs index ca9a13850a7..b9c20988922 100644 --- a/lib/api/tests/sys_export.rs +++ b/lib/api/tests/sys_export.rs @@ -106,10 +106,9 @@ mod sys { #[test] fn strong_weak_behavior_works_memory() -> Result<()> { - #[derive(Clone, Debug, WasmerEnv, Default)] + #[derive(Clone, Debug, Default)] struct MemEnv { - #[wasmer(export)] - memory: LazyInit, + memory: Option, } let host_fn = |env: &MemEnv| { @@ -129,7 +128,7 @@ mod sys { &module, &imports! { "env" => { - "host_fn" => Function::new_native_with_env(&store, env, host_fn) + "host_fn" => Function::new_native(&store, env, host_fn) } }, )?; @@ -150,10 +149,9 @@ mod sys { #[test] fn strong_weak_behavior_works_global() -> Result<()> { - #[derive(Clone, Debug, WasmerEnv, Default)] + #[derive(Clone, Debug, Default)] struct GlobalEnv { - #[wasmer(export)] - global: LazyInit, + global: Option, } let host_fn = |env: &GlobalEnv| { @@ -173,7 +171,7 @@ mod sys { &module, &imports! { "env" => { - "host_fn" => Function::new_native_with_env(&store, env, host_fn) + "host_fn" => Function::new_native(&store, env, host_fn) } }, )?; @@ -194,10 +192,9 @@ mod sys { #[test] fn strong_weak_behavior_works_table() -> Result<()> { - #[derive(Clone, WasmerEnv, Default)] + #[derive(Clone, Default)] struct TableEnv { - #[wasmer(export)] - table: LazyInit
, + table: Option
, } let host_fn = |env: &TableEnv| { @@ -217,7 +214,7 @@ mod sys { &module, &imports! { "env" => { - "host_fn" => Function::new_native_with_env(&store, env, host_fn) + "host_fn" => Function::new_native(&store, env, host_fn) } }, )?; @@ -238,10 +235,9 @@ mod sys { #[test] fn strong_weak_behavior_works_function() -> Result<()> { - #[derive(Clone, WasmerEnv, Default)] + #[derive(Clone, Default)] struct FunctionEnv { - #[wasmer(export)] - call_host_fn: LazyInit, + call_host_fn: Option, } let host_fn = |env: &FunctionEnv| { @@ -261,7 +257,7 @@ mod sys { &module, &imports! { "env" => { - "host_fn" => Function::new_native_with_env(&store, env, host_fn) + "host_fn" => Function::new_native(&store, env, host_fn) } }, )?; @@ -282,10 +278,9 @@ mod sys { #[test] fn strong_weak_behavior_works_native_function() -> Result<()> { - #[derive(Clone, WasmerEnv, Default)] + #[derive(Clone, Default)] struct FunctionEnv { - #[wasmer(export)] - call_host_fn: LazyInit>, + call_host_fn: Option>, } let host_fn = |env: &FunctionEnv| { @@ -314,7 +309,7 @@ mod sys { &module, &imports! { "env" => { - "host_fn" => Function::new_native_with_env(&store, env, host_fn) + "host_fn" => Function::new_native(&store, env, host_fn) } }, )?; diff --git a/lib/api/tests/sys_externals.rs b/lib/api/tests/sys_externals.rs index 45ad77da476..fffa9b62e59 100644 --- a/lib/api/tests/sys_externals.rs +++ b/lib/api/tests/sys_externals.rs @@ -211,19 +211,18 @@ mod sys { #[test] fn function_new_env() -> Result<()> { let store = Store::default(); - #[derive(Clone, WasmerEnv)] + #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; - let function = Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv| {}); + let function = Function::new_native(&store, my_env.clone(), |_env: &MyEnv| {}); assert_eq!(function.ty().clone(), FunctionType::new(vec![], vec![])); - let function = - Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv, _a: i32| {}); + let function = Function::new_native(&store, my_env.clone(), |_env: &MyEnv, _a: i32| {}); assert_eq!( function.ty().clone(), FunctionType::new(vec![Type::I32], vec![]) ); - let function = Function::new_native_with_env( + let function = Function::new_native( &store, my_env.clone(), |_env: &MyEnv, _a: i32, _b: i64, _c: f32, _d: f64| {}, @@ -232,14 +231,13 @@ mod sys { function.ty().clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = - Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv| -> i32 { 1 }); + let function = Function::new_native(&store, my_env.clone(), |_env: &MyEnv| -> i32 { 1 }); assert_eq!( function.ty().clone(), FunctionType::new(vec![], vec![Type::I32]) ); let function = - Function::new_native_with_env(&store, my_env, |_env: &MyEnv| -> (i32, i64, f32, f64) { + Function::new_native(&store, my_env, |_env: &MyEnv| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); assert_eq!( @@ -284,13 +282,13 @@ mod sys { #[test] fn function_new_dynamic_env() -> Result<()> { let store = Store::default(); - #[derive(Clone, WasmerEnv)] + #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new_with_env( + let function = Function::new( &store, &function_type, my_env.clone(), @@ -298,7 +296,7 @@ mod sys { ); assert_eq!(function.ty().clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new_with_env( + let function = Function::new( &store, &function_type, my_env.clone(), @@ -307,7 +305,7 @@ mod sys { assert_eq!(function.ty().clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new_with_env( + let function = Function::new( &store, &function_type, my_env.clone(), @@ -315,7 +313,7 @@ mod sys { ); assert_eq!(function.ty().clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new_with_env( + let function = Function::new( &store, &function_type, my_env.clone(), @@ -324,7 +322,7 @@ mod sys { assert_eq!(function.ty().clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new_with_env( + let function = Function::new( &store, &function_type, my_env.clone(), @@ -334,7 +332,7 @@ mod sys { // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new_with_env( + let function = Function::new( &store, function_type, my_env, @@ -438,10 +436,10 @@ mod sys { #[test] fn manually_generate_wasmer_env() -> Result<()> { let store = Store::default(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct MyEnv { val: u32, - memory: LazyInit, + memory: Option, } fn host_function(env: &mut MyEnv, arg1: u32, arg2: u32) -> u32 { @@ -450,7 +448,7 @@ mod sys { let mut env = MyEnv { val: 5, - memory: LazyInit::new(), + memory: None, }; let result = host_function(&mut env, 7, 9); diff --git a/lib/api/tests/sys_instance.rs b/lib/api/tests/sys_instance.rs index a89c5e6ceaf..8fd30b66a7d 100644 --- a/lib/api/tests/sys_instance.rs +++ b/lib/api/tests/sys_instance.rs @@ -43,7 +43,7 @@ mod sys { #[test] fn unit_native_function_env() -> Result<()> { let store = Store::default(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env { multiplier: u32, } @@ -54,7 +54,7 @@ mod sys { } let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env( + let imported = Function::new( &store, imported_signature, Env { multiplier: 3 }, diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs index 809103bfaca..0878fb2bd96 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/sys_reference_types.rs @@ -39,11 +39,11 @@ mod sys { panic!("funcref not found!"); } - #[derive(Clone, Debug, WasmerEnv)] + #[derive(Clone, Debug)] pub struct Env(Arc); let env = Env(Arc::new(AtomicBool::new(false))); - let func_to_call = Function::new_native_with_env(&store, env.clone(), |env: &Env| -> i32 { + let func_to_call = Function::new_native(&store, env.clone(), |env: &Env| -> i32 { env.0.store(true, Ordering::SeqCst); 343 }); diff --git a/lib/types/src/lib.rs b/lib/types/src/lib.rs index da185329db3..e04dadb6d73 100644 --- a/lib/types/src/lib.rs +++ b/lib/types/src/lib.rs @@ -132,6 +132,7 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION"); mod native { use super::Type; + use crate::memory::{Memory32, Memory64, MemorySize}; use std::fmt; /// `NativeWasmType` represents a Wasm type that has a direct @@ -183,6 +184,16 @@ mod native { type Abi = Self; } + impl NativeWasmType for Memory32 { + const WASM_TYPE: Type = <::Native as NativeWasmType>::WASM_TYPE; + type Abi = <::Native as NativeWasmType>::Abi; + } + + impl NativeWasmType for Memory64 { + const WASM_TYPE: Type = <::Native as NativeWasmType>::WASM_TYPE; + type Abi = <::Native as NativeWasmType>::Abi; + } + impl NativeWasmType for Option { const WASM_TYPE: Type = T::WASM_TYPE; type Abi = T::Abi; diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index 2940817142c..69c0f6b1cac 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -50,7 +50,7 @@ pub use crate::syscalls::types; pub use crate::utils::{ get_wasi_version, get_wasi_versions, is_wasi_module, is_wasix_module, WasiVersion, }; -use wasmer::{Context, ContextMut}; +use wasmer::ContextMut; pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus}; #[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")] pub use wasmer_vfs::FsError as WasiFsError; @@ -230,29 +230,29 @@ impl WasiEnv { } /// Get an `Imports` for a specific version of WASI detected in the module. - pub fn import_object(&mut self, module: &Module) -> Result { + pub fn import_object( + &mut self, + ctx: &mut ContextMut<'_, WasiEnv>, + module: &Module, + ) -> Result { let wasi_version = get_wasi_version(module, false).ok_or(WasiError::UnknownWasiVersion)?; - let mut context = Context::new(module.store(), self.clone()); - Ok(generate_import_object_from_ctx( - &mut context.as_context_mut(), - wasi_version, - )) + Ok(generate_import_object_from_ctx(ctx, wasi_version)) } /// Like `import_object` but containing all the WASI versions detected in /// the module. pub fn import_object_for_all_wasi_versions( &mut self, + ctx: &mut ContextMut<'_, WasiEnv>, module: &Module, ) -> Result { let wasi_versions = get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; let mut resolver = Imports::new(); - let mut context = Context::new(module.store(), self.clone()); for version in wasi_versions.iter() { let new_import_object = - generate_import_object_from_ctx(&mut context.as_context_mut(), *version); + generate_import_object_from_ctx(&mut ctx.as_context_mut(), *version); for ((n, m), e) in new_import_object.into_iter() { resolver.define(&n, &m, e); } diff --git a/lib/wasi/tests/stdio.rs b/lib/wasi/tests/stdio.rs index 45dcd57e4de..3af490b8d74 100644 --- a/lib/wasi/tests/stdio.rs +++ b/lib/wasi/tests/stdio.rs @@ -1,6 +1,6 @@ use std::io::{Read, Write}; -use wasmer::{Instance, Module, Store}; +use wasmer::{AsContextMut, Context, Instance, Module, Store}; use wasmer_wasi::{Pipe, WasiState}; mod sys { @@ -80,15 +80,22 @@ fn test_stdout() { .finalize() .unwrap(); + // Create a context state that will hold all objects created by this Instance + let mut ctx = Context::new(&store, wasi_env.clone()); + // Generate an `ImportObject`. - let import_object = wasi_env.import_object(&module).unwrap(); + let import_object = wasi_env + .import_object(&mut ctx.as_context_mut(), &module) + .unwrap(); // Let's instantiate the module with the imports. - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let memory = instance.exports.get_memory("memory").unwrap(); + ctx.data_mut().set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); - start.call(&[]).unwrap(); + start.call(&mut ctx, &[]).unwrap(); let mut stdout_str = String::new(); stdout.read_to_string(&mut stdout_str).unwrap(); @@ -121,15 +128,22 @@ fn test_env() { .finalize() .unwrap(); + // Create a context state that will hold all objects created by this Instance + let mut ctx = Context::new(&store, wasi_env.clone()); + // Generate an `ImportObject`. - let import_object = wasi_env.import_object(&module).unwrap(); + let import_object = wasi_env + .import_object(&mut ctx.as_context_mut(), &module) + .unwrap(); // Let's instantiate the module with the imports. - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let memory = instance.exports.get_memory("memory").unwrap(); + ctx.data_mut().set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); - start.call(&[]).unwrap(); + start.call(&mut ctx, &[]).unwrap(); let mut stdout_str = String::new(); stdout.read_to_string(&mut stdout_str).unwrap(); @@ -152,15 +166,22 @@ fn test_stdin() { let buf = "Hello, stdin!\n".as_bytes().to_owned(); stdin.write(&buf[..]).unwrap(); + // Create a context state that will hold all objects created by this Instance + let mut ctx = Context::new(&store, wasi_env.clone()); + // Generate an `ImportObject`. - let import_object = wasi_env.import_object(&module).unwrap(); + let import_object = wasi_env + .import_object(&mut ctx.as_context_mut(), &module) + .unwrap(); // Let's instantiate the module with the imports. - let instance = Instance::new(&module, &import_object).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let memory = instance.exports.get_memory("memory").unwrap(); + ctx.data_mut().set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); - let result = start.call(&[]); + let result = start.call(&mut ctx, &[]); assert!(!result.is_err()); // We assure stdin is now empty From b518e95b178bacef7cfdec6dc0430f6c7500e6d8 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Wed, 22 Jun 2022 14:06:45 +0200 Subject: [PATCH 13/24] Migrate metering to new Context API --- lib/middlewares/src/metering.rs | 57 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/lib/middlewares/src/metering.rs b/lib/middlewares/src/metering.rs index a90faca2388..49549952ba7 100644 --- a/lib/middlewares/src/metering.rs +++ b/lib/middlewares/src/metering.rs @@ -281,15 +281,12 @@ impl u64 + Send + Sync> FunctionMiddleware for FunctionMeter /// matches!(get_remaining_points(instance), MeteringPoints::Remaining(points) if points > 0) /// } /// ``` -pub fn get_remaining_points( - mut ctx: impl AsContextMut, - instance: &Instance, -) -> MeteringPoints { +pub fn get_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance) -> MeteringPoints { let exhausted: i32 = instance .exports .get_global("wasmer_metering_points_exhausted") .expect("Can't get `wasmer_metering_points_exhausted` from Instance") - .get(&mut ctx) + .get(ctx) .try_into() .expect("`wasmer_metering_points_exhausted` from Instance has wrong type"); @@ -301,7 +298,7 @@ pub fn get_remaining_points( .exports .get_global("wasmer_metering_remaining_points") .expect("Can't get `wasmer_metering_remaining_points` from Instance") - .get(&mut ctx) + .get(ctx) .try_into() .expect("`wasmer_metering_remaining_points` from Instance has wrong type"); @@ -334,23 +331,19 @@ pub fn get_remaining_points( /// set_remaining_points(instance, new_limit); /// } /// ``` -pub fn set_remaining_points( - mut ctx: impl AsContextMut, - instance: &Instance, - points: u64, -) { +pub fn set_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance, points: u64) { instance .exports .get_global("wasmer_metering_remaining_points") .expect("Can't get `wasmer_metering_remaining_points` from Instance") - .set(&mut ctx, points.into()) + .set(ctx, points.into()) .expect("Can't set `wasmer_metering_remaining_points` in Instance"); instance .exports .get_global("wasmer_metering_points_exhausted") .expect("Can't get `wasmer_metering_points_exhausted` from Instance") - .set(&mut ctx, 0i32.into()) + .set(ctx, 0i32.into()) .expect("Can't set `wasmer_metering_points_exhausted` in Instance"); } @@ -360,8 +353,8 @@ mod tests { use std::sync::Arc; use wasmer::{ - imports, wat2wasm, AsContextMut, CompilerConfig, Context, Cranelift, Module, Store, - TypedFunction, Universal, + imports, wat2wasm, CompilerConfig, Context, Cranelift, Module, Store, TypedFunction, + Universal, }; fn cost_function(operator: &Operator) -> u64 { @@ -395,12 +388,12 @@ mod tests { compiler_config.push_middleware(metering); let store = Store::new_with_engine(&Universal::new(compiler_config).engine()); let module = Module::new(&store, bytecode()).unwrap(); - let mut ctx = Context::new(module.store(), ()); + let mut ctx = Context::new(&store, ()); // Instantiate let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx.as_context_mut(), &instance), MeteringPoints::Remaining(10) ); @@ -418,21 +411,21 @@ mod tests { .unwrap(); add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx.as_context_mut(), &instance), MeteringPoints::Remaining(6) ); // Second call add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx.as_context_mut(), &instance), MeteringPoints::Remaining(2) ); // Third call fails due to limit assert!(add_one.call(&mut ctx.as_context_mut(), 1).is_err()); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx.as_context_mut(), &instance), MeteringPoints::Exhausted ); } @@ -449,7 +442,7 @@ mod tests { // Instantiate let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx, &instance), MeteringPoints::Remaining(10) ); let add_one: TypedFunction = instance @@ -460,37 +453,37 @@ mod tests { .unwrap(); // Increase a bit to have enough for 3 calls - set_remaining_points(ctx.as_context_mut(), &instance, 12); + set_remaining_points(&mut ctx, &instance, 12); // Ensure we can use the new points now - add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); + add_one.call(&mut &mut ctx, 1).unwrap(); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx, &instance), MeteringPoints::Remaining(8) ); - add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); + add_one.call(&mut &mut ctx, 1).unwrap(); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx, &instance), MeteringPoints::Remaining(4) ); - add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); + add_one.call(&mut &mut ctx, 1).unwrap(); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx, &instance), MeteringPoints::Remaining(0) ); - assert!(add_one.call(&mut ctx.as_context_mut(), 1).is_err()); + assert!(add_one.call(&mut &mut ctx, 1).is_err()); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx, &instance), MeteringPoints::Exhausted ); // Add some points for another call - set_remaining_points(ctx.as_context_mut(), &instance, 4); + set_remaining_points(&mut ctx, &instance, 4); assert_eq!( - get_remaining_points(ctx.as_context_mut(), &instance), + get_remaining_points(&mut ctx, &instance), MeteringPoints::Remaining(4) ); } From 267a09ce8edb432186c8e5639fa46217b89734a0 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Fri, 24 Jun 2022 16:47:47 +0200 Subject: [PATCH 14/24] Migrate compiler tests to the new Context API --- lib/api/src/sys/externals/function.rs | 178 +++---- lib/api/src/sys/imports.rs | 66 +-- lib/api/src/sys/native_type.rs | 3 +- lib/api/src/sys/value.rs | 65 ++- lib/api/tests/sys_export.rs | 334 ------------- lib/api/tests/sys_externals.rs | 374 ++++++++------ lib/api/tests/sys_instance.rs | 26 +- lib/api/tests/sys_module.rs | 68 ++- lib/api/tests/sys_reference_types.rs | 681 +++++++++++++------------- lib/derive/tests/basic.rs | 119 ----- lib/types/src/value.rs | 27 + tests/compilers/imports.rs | 359 ++++++++------ tests/compilers/issues.rs | 92 ++-- tests/compilers/metering.rs | 25 +- tests/compilers/middlewares.rs | 41 +- tests/compilers/native_functions.rs | 228 +++++---- tests/compilers/serialize.rs | 24 +- tests/compilers/traps.rs | 108 ++-- 18 files changed, 1349 insertions(+), 1469 deletions(-) delete mode 100644 lib/api/tests/sys_export.rs delete mode 100644 lib/derive/tests/basic.rs diff --git a/lib/api/src/sys/externals/function.rs b/lib/api/src/sys/externals/function.rs index cdb0d0ad641..9d6e2d64481 100644 --- a/lib/api/src/sys/externals/function.rs +++ b/lib/api/src/sys/externals/function.rs @@ -1229,19 +1229,23 @@ mod inner { #[cfg(test)] mod test_wasm_type_list { use super::*; + use crate::Context as WasmerContext; + use crate::Store; use wasmer_types::Type; - + /* #[test] fn test_from_array() { - assert_eq!(<()>::from_array([]), ()); - assert_eq!(::from_array([1]), (1i32)); - assert_eq!(<(i32, i64)>::from_array([1, 2]), (1i32, 2i64)); + let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); + assert_eq!(<()>::from_array(&mut ctx, []), ()); + assert_eq!(::from_array(&mut ctx, [RawValue{i32: 1}]), (1i32)); + assert_eq!(<(i32, i64)>::from_array(&mut ctx, [RawValue{i32:1}, RawValue{i64:2}]), (1i32, 2i64)); assert_eq!( - <(i32, i64, f32, f64)>::from_array([ - 1, - 2, - (3.1f32).to_bits().into(), - (4.2f64).to_bits().into() + <(i32, i64, f32, f64)>::from_array(&mut ctx, [ + RawValue{i32:1}, + RawValue{i64:2}, + RawValue{f32: 3.1f32}, + RawValue{f64: 4.2f64} ]), (1, 2, 3.1f32, 4.2f64) ); @@ -1249,33 +1253,37 @@ mod inner { #[test] fn test_into_array() { - assert_eq!(().into_array(), [0i128; 0]); - assert_eq!((1).into_array(), [1]); - assert_eq!((1i32, 2i64).into_array(), [1, 2]); + let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); + assert_eq!(().into_array(&mut ctx), [0i128; 0]); + assert_eq!((1i32).into_array(&mut ctx), [1i32]); + assert_eq!((1i32, 2i64).into_array(&mut ctx), [RawValue{i32: 1}, RawValue{i64: 2}]); assert_eq!( - (1i32, 2i32, 3.1f32, 4.2f64).into_array(), - [1, 2, (3.1f32).to_bits().into(), (4.2f64).to_bits().into()] + (1i32, 2i32, 3.1f32, 4.2f64).into_array(&mut ctx), + [RawValue{i32: 1}, RawValue{i32: 2}, RawValue{ f32: 3.1f32}, RawValue{f64: 4.2f64}] ); } - + */ #[test] fn test_empty_array() { assert_eq!(<()>::empty_array().len(), 0); assert_eq!(::empty_array().len(), 1); assert_eq!(<(i32, i64)>::empty_array().len(), 2); } - + /* #[test] fn test_from_c_struct() { - assert_eq!(<()>::from_c_struct(S0()), ()); - assert_eq!(::from_c_struct(S1(1)), (1i32)); - assert_eq!(<(i32, i64)>::from_c_struct(S2(1, 2)), (1i32, 2i64)); + let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); + assert_eq!(<()>::from_c_struct(&mut ctx, S0()), ()); + assert_eq!(::from_c_struct(&mut ctx, S1(1)), (1i32)); + assert_eq!(<(i32, i64)>::from_c_struct(&mut ctx, S2(1, 2)), (1i32, 2i64)); assert_eq!( - <(i32, i64, f32, f64)>::from_c_struct(S4(1, 2, 3.1, 4.2)), + <(i32, i64, f32, f64)>::from_c_struct(&mut ctx, S4(1, 2, 3.1, 4.2)), (1i32, 2i64, 3.1f32, 4.2f64) ); } - + */ #[test] fn test_wasm_types_for_uni_values() { assert_eq!(::wasm_types(), [Type::I32]); @@ -1297,68 +1305,74 @@ mod inner { ); } } + /* + #[allow(non_snake_case)] + #[cfg(test)] + mod test_function { + use super::*; + use crate::Store; + use crate::Context as WasmerContext; + use wasmer_types::Type; + + fn func() {} + fn func__i32() -> i32 { + 0 + } + fn func_i32( _a: i32) {} + fn func_i32__i32( a: i32) -> i32 { + a * 2 + } + fn func_i32_i32__i32( a: i32, b: i32) -> i32 { + a + b + } + fn func_i32_i32__i32_i32( a: i32, b: i32) -> (i32, i32) { + (a, b) + } + fn func_f32_i32__i32_f32( a: f32, b: i32) -> (i32, f32) { + (b, a) + } - #[allow(non_snake_case)] - #[cfg(test)] - mod test_function { - use super::*; - use wasmer_types::Type; - - fn func() {} - fn func__i32() -> i32 { - 0 - } - fn func_i32(_a: i32) {} - fn func_i32__i32(a: i32) -> i32 { - a * 2 - } - fn func_i32_i32__i32(a: i32, b: i32) -> i32 { - a + b - } - fn func_i32_i32__i32_i32(a: i32, b: i32) -> (i32, i32) { - (a, b) - } - fn func_f32_i32__i32_f32(a: f32, b: i32) -> (i32, f32) { - (b, a) - } - - #[test] - fn test_function_types() { - assert_eq!( - StaticFunction::new(func).ty(), - FunctionType::new(vec![], vec![]) - ); - assert_eq!( - StaticFunction::new(func__i32).ty(), - FunctionType::new(vec![], vec![Type::I32]) - ); - assert_eq!( - StaticFunction::new(func_i32).ty(), - FunctionType::new(vec![Type::I32], vec![]) - ); - assert_eq!( - StaticFunction::new(func_i32__i32).ty(), - FunctionType::new(vec![Type::I32], vec![Type::I32]) - ); - assert_eq!( - StaticFunction::new(func_i32_i32__i32).ty(), - FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]) - ); - assert_eq!( - StaticFunction::new(func_i32_i32__i32_i32).ty(), - FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]) - ); - assert_eq!( - StaticFunction::new(func_f32_i32__i32_f32).ty(), - FunctionType::new(vec![Type::F32, Type::I32], vec![Type::I32, Type::F32]) - ); - } + #[test] + fn test_function_types() { + let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); + use wasmer_types::FunctionType; + assert_eq!( + StaticFunction::new(func).ty(&mut ctx), + FunctionType::new(vec![], vec![]) + ); + assert_eq!( + StaticFunction::new(func__i32).ty(&mut ctx), + FunctionType::new(vec![], vec![Type::I32]) + ); + assert_eq!( + StaticFunction::new(func_i32).ty(), + FunctionType::new(vec![Type::I32], vec![]) + ); + assert_eq!( + StaticFunction::new(func_i32__i32).ty(), + FunctionType::new(vec![Type::I32], vec![Type::I32]) + ); + assert_eq!( + StaticFunction::new(func_i32_i32__i32).ty(), + FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]) + ); + assert_eq!( + StaticFunction::new(func_i32_i32__i32_i32).ty(), + FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]) + ); + assert_eq!( + StaticFunction::new(func_f32_i32__i32_f32).ty(), + FunctionType::new(vec![Type::F32, Type::I32], vec![Type::I32, Type::F32]) + ); + } - #[test] - fn test_function_pointer() { - let f = StaticFunction::new(func_i32__i32); - let function = unsafe { std::mem::transmute::<_, fn(usize, i32) -> i32>(f.address) }; - assert_eq!(function(0, 3), 6); + #[test] + fn test_function_pointer() { + let f = StaticFunction::new(func_i32__i32); + let function = unsafe { std::mem::transmute::<_, fn(usize, i32) -> i32>(f.address) }; + assert_eq!(function(0, 3), 6); + } } - } + */ } diff --git a/lib/api/src/sys/imports.rs b/lib/api/src/sys/imports.rs index 458108a852f..df5ee00c440 100644 --- a/lib/api/src/sys/imports.rs +++ b/lib/api/src/sys/imports.rs @@ -268,14 +268,17 @@ macro_rules! import_namespace { #[cfg(test)] mod test { use crate::sys::exports::Exportable; - use crate::sys::Export; - use crate::sys::{Global, Store, Val}; + use crate::sys::Context as WasmerContext; + use crate::sys::Exports; + use crate::sys::{Global, Store, Value}; use wasmer_types::Type; - + use wasmer_vm::VMExtern; + /* #[test] fn namespace() { let store = Store::default(); - let g1 = Global::new(&store, Val::I32(0)); + let mut ctx = WasmerContext::new(&store, ()); + let g1 = Global::new(&mut ctx, Value::I32(0)); let namespace = namespace! { "happy" => g1 }; @@ -286,62 +289,64 @@ mod test { let happy_dog_entry = imports1.get_export("dog", "happy").unwrap(); assert!( - if let Export::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { - happy_dog_global.from.ty().ty == Type::I32 + if let VMExtern::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { + happy_dog_global.get(&mut ctx).ty == Type::I32 } else { false } ); } - + */ #[test] fn imports_macro_allows_trailing_comma_and_none() { + use crate::sys::ContextMut; use crate::sys::Function; let store = Default::default(); + let mut ctx = WasmerContext::new(&store, ()); - fn func(arg: i32) -> i32 { + fn func(_ctx: ContextMut<()>, arg: i32) -> i32 { arg + 1 } let _ = imports! { "env" => { - "func" => Function::new_native(&store, func), + "func" => Function::new_native(&mut ctx, func), }, }; let _ = imports! { "env" => { - "func" => Function::new_native(&store, func), + "func" => Function::new_native(&mut ctx, func), } }; let _ = imports! { "env" => { - "func" => Function::new_native(&store, func), + "func" => Function::new_native(&mut ctx, func), }, "abc" => { - "def" => Function::new_native(&store, func), + "def" => Function::new_native(&mut ctx, func), } }; let _ = imports! { "env" => { - "func" => Function::new_native(&store, func) + "func" => Function::new_native(&mut ctx, func) }, }; let _ = imports! { "env" => { - "func" => Function::new_native(&store, func) + "func" => Function::new_native(&mut ctx, func) } }; let _ = imports! { "env" => { - "func1" => Function::new_native(&store, func), - "func2" => Function::new_native(&store, func) + "func1" => Function::new_native(&mut ctx, func), + "func2" => Function::new_native(&mut ctx, func) } }; let _ = imports! { "env" => { - "func1" => Function::new_native(&store, func), - "func2" => Function::new_native(&store, func), + "func1" => Function::new_native(&mut ctx, func), + "func2" => Function::new_native(&mut ctx, func), } }; } @@ -349,7 +354,9 @@ mod test { #[test] fn chaining_works() { let store = Store::default(); - let g = Global::new(&store, Val::I32(0)); + let mut ctx = WasmerContext::new(&store, ()); + + let g = Global::new(&mut ctx, Value::I32(0)); let mut imports1 = imports! { "dog" => { @@ -380,8 +387,9 @@ mod test { #[test] fn extending_conflict_overwrites() { let store = Store::default(); - let g1 = Global::new(&store, Val::I32(0)); - let g2 = Global::new(&store, Val::I64(0)); + let mut ctx = WasmerContext::new(&store, ()); + let g1 = Global::new(&mut ctx, Value::I32(0)); + let g2 = Global::new(&mut ctx, Value::I64(0)); let mut imports1 = imports! { "dog" => { @@ -397,19 +405,20 @@ mod test { imports1.extend(&imports2); let happy_dog_entry = imports1.get_export("dog", "happy").unwrap(); - + /* assert!( - if let Export::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { + if let Exports::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { happy_dog_global.from.ty().ty == Type::I64 } else { false } ); - + */ // now test it in reverse let store = Store::default(); - let g1 = Global::new(&store, Val::I32(0)); - let g2 = Global::new(&store, Val::I64(0)); + let mut ctx = WasmerContext::new(&store, ()); + let g1 = Global::new(&mut ctx, Value::I32(0)); + let g2 = Global::new(&mut ctx, Value::I64(0)); let imports1 = imports! { "dog" => { @@ -425,13 +434,14 @@ mod test { imports2.extend(&imports1); let happy_dog_entry = imports2.get_export("dog", "happy").unwrap(); - + /* assert!( - if let Export::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { + if let Exports::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { happy_dog_global.from.ty().ty == Type::I32 } else { false } ); + */ } } diff --git a/lib/api/src/sys/native_type.rs b/lib/api/src/sys/native_type.rs index 4429f9d7e43..746c3b21585 100644 --- a/lib/api/src/sys/native_type.rs +++ b/lib/api/src/sys/native_type.rs @@ -205,7 +205,7 @@ mod test_native_type { assert_eq!(f64::WASM_TYPE, Type::F64); assert_eq!(u128::WASM_TYPE, Type::V128); } - + /* #[test] fn test_roundtrip() { unsafe { @@ -216,6 +216,7 @@ mod test_native_type { assert_eq!(u128::from_raw(42u128.into_raw()), 42u128); } } + */ } // pub trait IntegerAtomic diff --git a/lib/api/src/sys/value.rs b/lib/api/src/sys/value.rs index 9e23a966e0d..03414a70483 100644 --- a/lib/api/src/sys/value.rs +++ b/lib/api/src/sys/value.rs @@ -190,6 +190,19 @@ impl ToString for Value { } } +impl PartialEq for Value { + fn eq(&self, o: &Self) -> bool { + match (self, o) { + (Self::I32(a), Self::I32(b)) => a == b, + (Self::I64(a), Self::I64(b)) => a == b, + (Self::F32(a), Self::F32(b)) => a == b, + (Self::F64(a), Self::F64(b)) => a == b, + (Self::V128(a), Self::V128(b)) => a == b, + _ => false, + } + } +} + impl From for Value { fn from(val: i32) -> Self { Self::I32(val) @@ -336,127 +349,127 @@ mod tests { #[test] fn test_value_i32_from_u32() { let bytes = [0x00, 0x00, 0x00, 0x00]; - let v = Value::<()>::from(u32::from_be_bytes(bytes)); + let v = Value::from(u32::from_be_bytes(bytes)); assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); let bytes = [0x00, 0x00, 0x00, 0x01]; - let v = Value::<()>::from(u32::from_be_bytes(bytes)); + let v = Value::from(u32::from_be_bytes(bytes)); assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); let bytes = [0xAA, 0xBB, 0xCC, 0xDD]; - let v = Value::<()>::from(u32::from_be_bytes(bytes)); + let v = Value::from(u32::from_be_bytes(bytes)); assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); let bytes = [0xFF, 0xFF, 0xFF, 0xFF]; - let v = Value::<()>::from(u32::from_be_bytes(bytes)); + let v = Value::from(u32::from_be_bytes(bytes)); assert_eq!(v, Value::I32(i32::from_be_bytes(bytes))); } #[test] fn test_value_i64_from_u64() { let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let v = Value::<()>::from(u64::from_be_bytes(bytes)); + let v = Value::from(u64::from_be_bytes(bytes)); assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); let bytes = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]; - let v = Value::<()>::from(u64::from_be_bytes(bytes)); + let v = Value::from(u64::from_be_bytes(bytes)); assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); let bytes = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11]; - let v = Value::<()>::from(u64::from_be_bytes(bytes)); + let v = Value::from(u64::from_be_bytes(bytes)); assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; - let v = Value::<()>::from(u64::from_be_bytes(bytes)); + let v = Value::from(u64::from_be_bytes(bytes)); assert_eq!(v, Value::I64(i64::from_be_bytes(bytes))); } #[test] fn convert_value_to_i32() { - let value = Value::<()>::I32(5678); + let value = Value::I32(5678); let result = i32::try_from(value); assert_eq!(result.unwrap(), 5678); - let value = Value::<()>::from(u32::MAX); + let value = Value::from(u32::MAX); let result = i32::try_from(value); assert_eq!(result.unwrap(), -1); - let value = Value::<()>::V128(42); + let value = Value::V128(42); let result = i32::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type i32"); } #[test] fn convert_value_to_u32() { - let value = Value::<()>::from(u32::MAX); + let value = Value::from(u32::MAX); let result = u32::try_from(value); assert_eq!(result.unwrap(), u32::MAX); - let value = Value::<()>::I32(-1); + let value = Value::I32(-1); let result = u32::try_from(value); assert_eq!(result.unwrap(), u32::MAX); - let value = Value::<()>::V128(42); + let value = Value::V128(42); let result = u32::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type i32"); } #[test] fn convert_value_to_i64() { - let value = Value::<()>::I64(5678); + let value = Value::I64(5678); let result = i64::try_from(value); assert_eq!(result.unwrap(), 5678); - let value = Value::<()>::from(u64::MAX); + let value = Value::from(u64::MAX); let result = i64::try_from(value); assert_eq!(result.unwrap(), -1); - let value = Value::<()>::V128(42); + let value = Value::V128(42); let result = i64::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type i64"); } #[test] fn convert_value_to_u64() { - let value = Value::<()>::from(u64::MAX); + let value = Value::from(u64::MAX); let result = u64::try_from(value); assert_eq!(result.unwrap(), u64::MAX); - let value = Value::<()>::I64(-1); + let value = Value::I64(-1); let result = u64::try_from(value); assert_eq!(result.unwrap(), u64::MAX); - let value = Value::<()>::V128(42); + let value = Value::V128(42); let result = u64::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type i64"); } #[test] fn convert_value_to_f32() { - let value = Value::<()>::F32(1.234); + let value = Value::F32(1.234); let result = f32::try_from(value); assert_eq!(result.unwrap(), 1.234); - let value = Value::<()>::V128(42); + let value = Value::V128(42); let result = f32::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type f32"); - let value = Value::<()>::F64(1.234); + let value = Value::F64(1.234); let result = f32::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type f32"); } #[test] fn convert_value_to_f64() { - let value = Value::<()>::F64(1.234); + let value = Value::F64(1.234); let result = f64::try_from(value); assert_eq!(result.unwrap(), 1.234); - let value = Value::<()>::V128(42); + let value = Value::V128(42); let result = f64::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type f64"); - let value = Value::<()>::F32(1.234); + let value = Value::F32(1.234); let result = f64::try_from(value); assert_eq!(result.unwrap_err(), "Value is not of Wasm type f64"); } diff --git a/lib/api/tests/sys_export.rs b/lib/api/tests/sys_export.rs deleted file mode 100644 index b9c20988922..00000000000 --- a/lib/api/tests/sys_export.rs +++ /dev/null @@ -1,334 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use wasmer::*; - use wasmer_vm::WeakOrStrongInstanceRef; - - const MEM_WAT: &str = " - (module - (func $host_fn (import \"env\" \"host_fn\") (param) (result)) - (func (export \"call_host_fn\") (param) (result) - (call $host_fn)) - - (memory $mem 0) - (export \"memory\" (memory $mem)) - ) -"; - - const GLOBAL_WAT: &str = " - (module - (func $host_fn (import \"env\" \"host_fn\") (param) (result)) - (func (export \"call_host_fn\") (param) (result) - (call $host_fn)) - - (global $global i32 (i32.const 11)) - (export \"global\" (global $global)) - ) -"; - - const TABLE_WAT: &str = " - (module - (func $host_fn (import \"env\" \"host_fn\") (param) (result)) - (func (export \"call_host_fn\") (param) (result) - (call $host_fn)) - - (table $table 4 4 funcref) - (export \"table\" (table $table)) - ) -"; - - const FUNCTION_WAT: &str = " - (module - (func $host_fn (import \"env\" \"host_fn\") (param) (result)) - (func (export \"call_host_fn\") (param) (result) - (call $host_fn)) - ) -"; - - fn is_memory_instance_ref_strong(memory: &Memory) -> Option { - // This is safe because we're calling it from a test to test the internals - unsafe { - memory - .get_vm_memory() - .instance_ref - .as_ref() - .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_))) - } - } - - fn is_table_instance_ref_strong(table: &Table) -> Option { - // This is safe because we're calling it from a test to test the internals - unsafe { - table - .get_vm_table() - .instance_ref - .as_ref() - .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_))) - } - } - - fn is_global_instance_ref_strong(global: &Global) -> Option { - // This is safe because we're calling it from a test to test the internals - unsafe { - global - .get_vm_global() - .instance_ref - .as_ref() - .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_))) - } - } - - fn is_function_instance_ref_strong(f: &Function) -> Option { - // This is safe because we're calling it from a test to test the internals - unsafe { - f.get_vm_function() - .instance_ref - .as_ref() - .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_))) - } - } - - fn is_native_function_instance_ref_strong( - f: &TypedFunction, - ) -> Option - where - Args: WasmTypeList, - Rets: WasmTypeList, - { - // This is safe because we're calling it from a test to test the internals - unsafe { - f.get_vm_function() - .instance_ref - .as_ref() - .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_))) - } - } - - #[test] - fn strong_weak_behavior_works_memory() -> Result<()> { - #[derive(Clone, Debug, Default)] - struct MemEnv { - memory: Option, - } - - let host_fn = |env: &MemEnv| { - let mem = env.memory_ref().unwrap(); - assert_eq!(is_memory_instance_ref_strong(mem), Some(false)); - let mem_clone = mem.clone(); - assert_eq!(is_memory_instance_ref_strong(&mem_clone), Some(true)); - assert_eq!(is_memory_instance_ref_strong(mem), Some(false)); - }; - - let f: TypedFunction<(), ()> = { - let store = Store::default(); - let module = Module::new(&store, MEM_WAT)?; - let env = MemEnv::default(); - - let instance = Instance::new( - &module, - &imports! { - "env" => { - "host_fn" => Function::new_native(&store, env, host_fn) - } - }, - )?; - - { - let mem = instance.exports.get_memory("memory")?; - assert_eq!(is_memory_instance_ref_strong(mem), Some(true)); - } - - let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; - f.call()?; - f - }; - f.call()?; - - Ok(()) - } - - #[test] - fn strong_weak_behavior_works_global() -> Result<()> { - #[derive(Clone, Debug, Default)] - struct GlobalEnv { - global: Option, - } - - let host_fn = |env: &GlobalEnv| { - let global = env.global_ref().unwrap(); - assert_eq!(is_global_instance_ref_strong(global), Some(false)); - let global_clone = global.clone(); - assert_eq!(is_global_instance_ref_strong(&global_clone), Some(true)); - assert_eq!(is_global_instance_ref_strong(global), Some(false)); - }; - - let f: TypedFunction<(), ()> = { - let store = Store::default(); - let module = Module::new(&store, GLOBAL_WAT)?; - let env = GlobalEnv::default(); - - let instance = Instance::new( - &module, - &imports! { - "env" => { - "host_fn" => Function::new_native(&store, env, host_fn) - } - }, - )?; - - { - let global = instance.exports.get_global("global")?; - assert_eq!(is_global_instance_ref_strong(global), Some(true)); - } - - let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; - f.call()?; - f - }; - f.call()?; - - Ok(()) - } - - #[test] - fn strong_weak_behavior_works_table() -> Result<()> { - #[derive(Clone, Default)] - struct TableEnv { - table: Option
, - } - - let host_fn = |env: &TableEnv| { - let table = env.table_ref().unwrap(); - assert_eq!(is_table_instance_ref_strong(table), Some(false)); - let table_clone = table.clone(); - assert_eq!(is_table_instance_ref_strong(&table_clone), Some(true)); - assert_eq!(is_table_instance_ref_strong(table), Some(false)); - }; - - let f: TypedFunction<(), ()> = { - let store = Store::default(); - let module = Module::new(&store, TABLE_WAT)?; - let env = TableEnv::default(); - - let instance = Instance::new( - &module, - &imports! { - "env" => { - "host_fn" => Function::new_native(&store, env, host_fn) - } - }, - )?; - - { - let table = instance.exports.get_table("table")?; - assert_eq!(is_table_instance_ref_strong(table), Some(true)); - } - - let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; - f.call()?; - f - }; - f.call()?; - - Ok(()) - } - - #[test] - fn strong_weak_behavior_works_function() -> Result<()> { - #[derive(Clone, Default)] - struct FunctionEnv { - call_host_fn: Option, - } - - let host_fn = |env: &FunctionEnv| { - let function = env.call_host_fn_ref().unwrap(); - assert_eq!(is_function_instance_ref_strong(function), Some(false)); - let function_clone = function.clone(); - assert_eq!(is_function_instance_ref_strong(&function_clone), Some(true)); - assert_eq!(is_function_instance_ref_strong(function), Some(false)); - }; - - let f: TypedFunction<(), ()> = { - let store = Store::default(); - let module = Module::new(&store, FUNCTION_WAT)?; - let env = FunctionEnv::default(); - - let instance = Instance::new( - &module, - &imports! { - "env" => { - "host_fn" => Function::new_native(&store, env, host_fn) - } - }, - )?; - - { - let function = instance.exports.get_function("call_host_fn")?; - assert_eq!(is_function_instance_ref_strong(function), Some(true)); - } - - let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; - f.call()?; - f - }; - f.call()?; - - Ok(()) - } - - #[test] - fn strong_weak_behavior_works_native_function() -> Result<()> { - #[derive(Clone, Default)] - struct FunctionEnv { - call_host_fn: Option>, - } - - let host_fn = |env: &FunctionEnv| { - let function = env.call_host_fn_ref().unwrap(); - assert_eq!( - is_native_function_instance_ref_strong(function), - Some(false) - ); - let function_clone = function.clone(); - assert_eq!( - is_native_function_instance_ref_strong(&function_clone), - Some(true) - ); - assert_eq!( - is_native_function_instance_ref_strong(function), - Some(false) - ); - }; - - let f: TypedFunction<(), ()> = { - let store = Store::default(); - let module = Module::new(&store, FUNCTION_WAT)?; - let env = FunctionEnv::default(); - - let instance = Instance::new( - &module, - &imports! { - "env" => { - "host_fn" => Function::new_native(&store, env, host_fn) - } - }, - )?; - - { - let function: TypedFunction<(), ()> = - instance.exports.get_typed_function("call_host_fn")?; - assert_eq!( - is_native_function_instance_ref_strong(&function), - Some(true) - ); - } - - let f: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_fn")?; - f.call()?; - f - }; - f.call()?; - - Ok(()) - } -} diff --git a/lib/api/tests/sys_externals.rs b/lib/api/tests/sys_externals.rs index fffa9b62e59..d23ab50eeed 100644 --- a/lib/api/tests/sys_externals.rs +++ b/lib/api/tests/sys_externals.rs @@ -1,23 +1,25 @@ #[cfg(feature = "sys")] mod sys { use anyhow::Result; + use wasmer::Context as WasmerContext; use wasmer::*; #[test] fn global_new() -> Result<()> { let store = Store::default(); - let global = Global::new(&store, Value::I32(10)); + let mut ctx = WasmerContext::new(&store, ()); + let global = Global::new(&mut ctx, Value::I32(10)); assert_eq!( - *global.ty(), + global.ty(&mut ctx), GlobalType { ty: Type::I32, mutability: Mutability::Const } ); - let global_mut = Global::new_mut(&store, Value::I32(10)); + let global_mut = Global::new_mut(&mut ctx, Value::I32(10)); assert_eq!( - *global_mut.ty(), + global_mut.ty(&mut ctx), GlobalType { ty: Type::I32, mutability: Mutability::Var @@ -30,14 +32,15 @@ mod sys { #[test] fn global_get() -> Result<()> { let store = Store::default(); - let global_i32 = Global::new(&store, Value::I32(10)); - assert_eq!(global_i32.get(), Value::I32(10)); - let global_i64 = Global::new(&store, Value::I64(20)); - assert_eq!(global_i64.get(), Value::I64(20)); - let global_f32 = Global::new(&store, Value::F32(10.0)); - assert_eq!(global_f32.get(), Value::F32(10.0)); - let global_f64 = Global::new(&store, Value::F64(20.0)); - assert_eq!(global_f64.get(), Value::F64(20.0)); + let mut ctx = WasmerContext::new(&store, ()); + let global_i32 = Global::new(&mut ctx, Value::I32(10)); + assert_eq!(global_i32.get(&mut ctx), Value::I32(10)); + let global_i64 = Global::new(&mut ctx, Value::I64(20)); + assert_eq!(global_i64.get(&mut ctx), Value::I64(20)); + let global_f32 = Global::new(&mut ctx, Value::F32(10.0)); + assert_eq!(global_f32.get(&mut ctx), Value::F32(10.0)); + let global_f64 = Global::new(&mut ctx, Value::F64(20.0)); + assert_eq!(global_f64.get(&mut ctx), Value::F64(20.0)); Ok(()) } @@ -45,17 +48,18 @@ mod sys { #[test] fn global_set() -> Result<()> { let store = Store::default(); - let global_i32 = Global::new(&store, Value::I32(10)); + let mut ctx = WasmerContext::new(&store, ()); + let global_i32 = Global::new(&mut ctx, Value::I32(10)); // Set on a constant should error - assert!(global_i32.set(Value::I32(20)).is_err()); + assert!(global_i32.set(&mut ctx, Value::I32(20)).is_err()); - let global_i32_mut = Global::new_mut(&store, Value::I32(10)); + let global_i32_mut = Global::new_mut(&mut ctx, Value::I32(10)); // Set on different type should error - assert!(global_i32_mut.set(Value::I64(20)).is_err()); + assert!(global_i32_mut.set(&mut ctx, Value::I64(20)).is_err()); // Set on same type should succeed - global_i32_mut.set(Value::I32(20))?; - assert_eq!(global_i32_mut.get(), Value::I32(20)); + global_i32_mut.set(&mut ctx, Value::I32(20))?; + assert_eq!(global_i32_mut.get(&mut ctx), Value::I32(20)); Ok(()) } @@ -63,14 +67,15 @@ mod sys { #[test] fn table_new() -> Result<()> { let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: None, }; - let f = Function::new_native(&store, || {}); - let table = Table::new(&store, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(*table.ty(), table_type); + let f = Function::new_native(&mut ctx, |_ctx: ContextMut<()>| {}); + let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f)))?; + assert_eq!(table.ty(&mut ctx), table_type); // Anyrefs not yet supported // let table_type = TableType { @@ -88,15 +93,16 @@ mod sys { #[ignore] fn table_get() -> Result<()> { let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: Some(1), }; - let f = Function::new_native(&store, |num: i32| num + 1); - let table = Table::new(&store, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(*table.ty(), table_type); - let _elem = table.get(0).unwrap(); + let f = Function::new_native(&mut ctx, |_ctx: ContextMut<()>, num: i32| num + 1); + let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f)))?; + assert_eq!(table.ty(&mut ctx), table_type); + let _elem = table.get(&mut ctx, 0).unwrap(); // assert_eq!(elem.funcref().unwrap(), f); Ok(()) } @@ -111,19 +117,20 @@ mod sys { #[test] fn table_grow() -> Result<()> { let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: Some(10), }; - let f = Function::new_native(&store, |num: i32| num + 1); - let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; + let f = Function::new_native(&mut ctx, |_ctx: ContextMut<()>, num: i32| num + 1); + let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f.clone())))?; // Growing to a bigger maximum should return None - let old_len = table.grow(12, Value::FuncRef(Some(f.clone()))); + let old_len = table.grow(&mut ctx, 12, Value::FuncRef(Some(f.clone()))); assert!(old_len.is_err()); // Growing to a bigger maximum should return None - let old_len = table.grow(5, Value::FuncRef(Some(f)))?; + let old_len = table.grow(&mut ctx, 5, Value::FuncRef(Some(f)))?; assert_eq!(old_len, 0); Ok(()) @@ -139,30 +146,31 @@ mod sys { #[test] fn memory_new() -> Result<()> { let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); let memory_type = MemoryType { shared: false, minimum: Pages(0), maximum: Some(Pages(10)), }; - let memory = Memory::new(&store, memory_type)?; - assert_eq!(memory.size(), Pages(0)); - assert_eq!(memory.ty(), memory_type); + let memory = Memory::new(&mut ctx, memory_type)?; + assert_eq!(memory.size(&mut ctx), Pages(0)); + assert_eq!(memory.ty(&mut ctx), memory_type); Ok(()) } #[test] fn memory_grow() -> Result<()> { let store = Store::default(); - + let mut ctx = WasmerContext::new(&store, ()); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&store, desc)?; - assert_eq!(memory.size(), Pages(10)); + let memory = Memory::new(&mut ctx, desc)?; + assert_eq!(memory.size(&mut ctx), Pages(10)); - let result = memory.grow(Pages(2)).unwrap(); + let result = memory.grow(&mut ctx, Pages(2)).unwrap(); assert_eq!(result, Pages(10)); - assert_eq!(memory.size(), Pages(12)); + assert_eq!(memory.size(&mut ctx), Pages(12)); - let result = memory.grow(Pages(10)); + let result = memory.grow(&mut ctx, Pages(10)); assert_eq!( result, Err(MemoryError::CouldNotGrow { @@ -172,7 +180,7 @@ mod sys { ); let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); - let bad_result = Memory::new(&store, bad_desc); + let bad_result = Memory::new(&mut ctx, bad_desc); assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); @@ -182,27 +190,36 @@ mod sys { #[test] fn function_new() -> Result<()> { let store = Store::default(); - let function = Function::new_native(&store, || {}); - assert_eq!(function.ty().clone(), FunctionType::new(vec![], vec![])); - let function = Function::new_native(&store, |_a: i32| {}); + let mut ctx = WasmerContext::new(&store, ()); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| {}); + assert_eq!( + function.ty(&mut ctx).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, _a: i32| {}); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![Type::I32], vec![]) ); - let function = Function::new_native(&store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); + let function = Function::new_native( + &mut ctx, + |_ctx: ContextMut<_>, _a: i32, _b: i64, _c: f32, _d: f64| {}, + ); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = Function::new_native(&store, || -> i32 { 1 }); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| -> i32 { 1 }); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![], vec![Type::I32]) ); let function = - Function::new_native(&store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); + Function::new_native(&mut ctx, |_ctx: ContextMut<_>| -> (i32, i64, f32, f64) { + (1, 2, 3.0, 4.0) + }); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); Ok(()) @@ -215,33 +232,36 @@ mod sys { struct MyEnv {} let my_env = MyEnv {}; - let function = Function::new_native(&store, my_env.clone(), |_env: &MyEnv| {}); - assert_eq!(function.ty().clone(), FunctionType::new(vec![], vec![])); - let function = Function::new_native(&store, my_env.clone(), |_env: &MyEnv, _a: i32| {}); + let mut ctx = WasmerContext::new(&store, my_env); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut| {}); + assert_eq!( + function.ty(&mut ctx).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut, _a: i32| {}); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![Type::I32], vec![]) ); let function = Function::new_native( - &store, - my_env.clone(), - |_env: &MyEnv, _a: i32, _b: i64, _c: f32, _d: f64| {}, + &mut ctx, + |_ctx: ContextMut, _a: i32, _b: i64, _c: f32, _d: f64| {}, ); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = Function::new_native(&store, my_env.clone(), |_env: &MyEnv| -> i32 { 1 }); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut| -> i32 { 1 }); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![], vec![Type::I32]) ); - let function = - Function::new_native(&store, my_env, |_env: &MyEnv| -> (i32, i64, f32, f64) { - (1, 2, 3.0, 4.0) - }); + let function = Function::new_native( + &mut ctx, + |_ctx: ContextMut| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + ); assert_eq!( - function.ty().clone(), + function.ty(&mut ctx).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); Ok(()) @@ -250,31 +270,59 @@ mod sys { #[test] fn function_new_dynamic() -> Result<()> { let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().clone(), function_type); + let function = Function::new( + &mut ctx, + &function_type, + |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut ctx).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new(&store, function_type, |_values: &[Value]| unimplemented!()); - assert_eq!(function.ty().params(), [Type::V128]); - assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]); + let function = Function::new( + &mut ctx, + function_type, + |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut ctx).params(), [Type::V128]); + assert_eq!( + function.ty(&mut ctx).results(), + [Type::I32, Type::F32, Type::F64] + ); Ok(()) } @@ -285,61 +333,59 @@ mod sys { #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; + let mut ctx = WasmerContext::new(&store, my_env); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); let function = Function::new( - &store, + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); let function = Function::new( - &store, + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function = Function::new( - &store, + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); let function = Function::new( - &store, + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&mut ctx).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function = Function::new( - &store, + &mut ctx, &function_type, - my_env.clone(), - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty().clone(), function_type); + assert_eq!(function.ty(&mut ctx).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); let function = Function::new( - &store, + &mut ctx, function_type, - my_env, - |_env: &MyEnv, _values: &[Value]| unimplemented!(), + |_ctx: ContextMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut ctx).params(), [Type::V128]); + assert_eq!( + function.ty(&mut ctx).results(), + [Type::I32, Type::F32, Type::F64] ); - assert_eq!(function.ty().params(), [Type::V128]); - assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]); Ok(()) } @@ -347,34 +393,40 @@ mod sys { #[test] fn native_function_works() -> Result<()> { let store = Store::default(); - let function = Function::new_native(&store, || {}); - let native_function: TypedFunction<(), ()> = function.native().unwrap(); - let result = native_function.call(); + let mut ctx = WasmerContext::new(&store, ()); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<()>| {}); + let native_function: TypedFunction<(), ()> = function.native(&mut ctx).unwrap(); + let result = native_function.call(&mut ctx); assert!(result.is_ok()); - let function = Function::new_native(&store, |a: i32| -> i32 { a + 1 }); - let native_function: TypedFunction = function.native().unwrap(); - assert_eq!(native_function.call(3).unwrap(), 4); + let function = + Function::new_native(&mut ctx, |_ctx: ContextMut<()>, a: i32| -> i32 { a + 1 }); + let native_function: TypedFunction = function.native(&mut ctx).unwrap(); + assert_eq!(native_function.call(&mut ctx, 3).unwrap(), 4); - fn rust_abi(a: i32, b: i64, c: f32, d: f64) -> u64 { + fn rust_abi(_ctx: ContextMut<()>, a: i32, b: i64, c: f32, d: f64) -> u64 { (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) } - let function = Function::new_native(&store, rust_abi); - let native_function: TypedFunction<(i32, i64, f32, f64), u64> = function.native().unwrap(); - assert_eq!(native_function.call(8, 4, 1.5, 5.).unwrap(), 8415); + let function = Function::new_native(&mut ctx, rust_abi); + let native_function: TypedFunction<(i32, i64, f32, f64), u64> = + function.native(&mut ctx).unwrap(); + assert_eq!(native_function.call(&mut ctx, 8, 4, 1.5, 5.).unwrap(), 8415); - let function = Function::new_native(&store, || -> i32 { 1 }); - let native_function: TypedFunction<(), i32> = function.native().unwrap(); - assert_eq!(native_function.call().unwrap(), 1); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<()>| -> i32 { 1 }); + let native_function: TypedFunction<(), i32> = function.native(&mut ctx).unwrap(); + assert_eq!(native_function.call(&mut ctx).unwrap(), 1); - let function = Function::new_native(&store, |_a: i32| {}); - let native_function: TypedFunction = function.native().unwrap(); - assert!(native_function.call(4).is_ok()); + let function = Function::new_native(&mut ctx, |_ctx: ContextMut<()>, _a: i32| {}); + let native_function: TypedFunction = function.native(&mut ctx).unwrap(); + assert!(native_function.call(&mut ctx, 4).is_ok()); let function = - Function::new_native(&store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - let native_function: TypedFunction<(), (i32, i64, f32, f64)> = function.native().unwrap(); - assert_eq!(native_function.call().unwrap(), (1, 2, 3.0, 4.0)); + Function::new_native(&mut ctx, |_ctx: ContextMut<()>| -> (i32, i64, f32, f64) { + (1, 2, 3.0, 4.0) + }); + let native_function: TypedFunction<(), (i32, i64, f32, f64)> = + function.native(&mut ctx).unwrap(); + assert_eq!(native_function.call(&mut ctx).unwrap(), (1, 2, 3.0, 4.0)); Ok(()) } @@ -382,6 +434,7 @@ mod sys { #[test] fn function_outlives_instance() -> Result<()> { let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); let wat = r#"(module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) @@ -393,46 +446,48 @@ mod sys { let f = { let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("sum")?; - - assert_eq!(f.call(4, 5)?, 9); - f - }; - - assert_eq!(f.call(4, 5)?, 9); - - Ok(()) - } - - #[test] - fn weak_instance_ref_externs_after_instance() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (memory (export "mem") 1) - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export "sum" (func $sum_f))) -"#; - - let f = { - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + let instance = Instance::new(&mut ctx, &module, &imports! {})?; let f: TypedFunction<(i32, i32), i32> = - instance.exports.get_with_generics_weak("sum")?; + instance.exports.get_typed_function(&mut ctx, "sum")?; - assert_eq!(f.call(4, 5)?, 9); + assert_eq!(f.call(&mut ctx, 4, 5)?, 9); f }; - assert_eq!(f.call(4, 5)?, 9); + assert_eq!(f.call(&mut ctx, 4, 5)?, 9); Ok(()) } - + /* + #[test] + fn weak_instance_ref_externs_after_instance() -> Result<()> { + let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); + let wat = r#"(module + (memory (export "mem") 1) + (type $sum_t (func (param i32 i32) (result i32))) + (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) + local.get $x + local.get $y + i32.add) + (export "sum" (func $sum_f))) + "#; + + let f = { + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_with_generics_weak("sum")?; + + assert_eq!(f.call(&mut ctx, 4, 5)?, 9); + f + }; + + assert_eq!(f.call(&mut ctx, 4, 5)?, 9); + + Ok(()) + } + */ #[test] fn manually_generate_wasmer_env() -> Result<()> { let store = Store::default(); @@ -442,22 +497,23 @@ mod sys { memory: Option, } - fn host_function(env: &mut MyEnv, arg1: u32, arg2: u32) -> u32 { - env.val + arg1 + arg2 + fn host_function(ctx: ContextMut, arg1: u32, arg2: u32) -> u32 { + ctx.data().val + arg1 + arg2 } let mut env = MyEnv { val: 5, memory: None, }; + let mut ctx = WasmerContext::new(&store, env); - let result = host_function(&mut env, 7, 9); + let result = host_function(ctx.as_context_mut(), 7, 9); assert_eq!(result, 21); - let memory = Memory::new(&store, MemoryType::new(0, None, false))?; - env.memory.initialize(memory); + let memory = Memory::new(&mut ctx, MemoryType::new(0, None, false))?; + ctx.data_mut().memory = Some(memory); - let result = host_function(&mut env, 1, 2); + let result = host_function(ctx.as_context_mut(), 1, 2); assert_eq!(result, 8); Ok(()) diff --git a/lib/api/tests/sys_instance.rs b/lib/api/tests/sys_instance.rs index 8fd30b66a7d..d3eac9255eb 100644 --- a/lib/api/tests/sys_instance.rs +++ b/lib/api/tests/sys_instance.rs @@ -1,11 +1,13 @@ #[cfg(feature = "sys")] mod sys { use anyhow::Result; + use wasmer::Context as WasmerContext; use wasmer::*; #[test] fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); let module = Module::new( &store, " @@ -20,7 +22,7 @@ mod sys { )?; let imports = Imports::new(); - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&mut ctx, &module, &imports)?; let instance2 = instance.clone(); let instance3 = instance.clone(); @@ -33,7 +35,8 @@ mod sys { // All instances have been dropped, but `sum` continues to work! assert_eq!( - sum.call(&[Value::I32(1), Value::I32(2)])?.into_vec(), + sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])? + .into_vec(), vec![Value::I32(3)], ); @@ -48,21 +51,18 @@ mod sys { multiplier: u32, } - fn imported_fn(env: &Env, args: &[Val]) -> Result, RuntimeError> { - let value = env.multiplier * args[0].unwrap_i32() as u32; - Ok(vec![Val::I32(value as _)]) + fn imported_fn(ctx: ContextMut, args: &[Value]) -> Result, RuntimeError> { + let value = ctx.data().multiplier * args[0].unwrap_i32() as u32; + Ok(vec![Value::I32(value as _)]) } + let env = Env { multiplier: 3 }; + let mut ctx = WasmerContext::new(&store, env); let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new( - &store, - imported_signature, - Env { multiplier: 3 }, - imported_fn, - ); + let imported = Function::new(&mut ctx, imported_signature, imported_fn); - let expected = vec![Val::I32(12)].into_boxed_slice(); - let result = imported.call(&[Val::I32(4)])?; + let expected = vec![Value::I32(12)].into_boxed_slice(); + let result = imported.call(&mut ctx, &[Value::I32(4)])?; assert_eq!(result, expected); Ok(()) diff --git a/lib/api/tests/sys_module.rs b/lib/api/tests/sys_module.rs index 1b0bbf27d71..7b5cf58f290 100644 --- a/lib/api/tests/sys_module.rs +++ b/lib/api/tests/sys_module.rs @@ -1,6 +1,7 @@ #[cfg(feature = "sys")] mod sys { use anyhow::Result; + use wasmer::Context as WasmerContext; use wasmer::*; #[test] @@ -190,61 +191,78 @@ mod sys { (call 7 (i32.const -1))) )"#; let module = Module::new(&store, wat)?; + let mut ctx = WasmerContext::new(&store, ()); let imports = imports! { "host" => { - "host_func1" => Function::new_native(&store, |p: u64| { + "host_func1" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u64| { println!("host_func1: Found number {}", p); assert_eq!(p, u64::max_value()); }), - "host_func2" => Function::new_native(&store, |p: u32| { + "host_func2" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u32| { println!("host_func2: Found number {}", p); assert_eq!(p, u32::max_value()); }), - "host_func3" => Function::new_native(&store, |p: i64| { + "host_func3" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i64| { println!("host_func3: Found number {}", p); assert_eq!(p, -1); }), - "host_func4" => Function::new_native(&store, |p: i32| { + "host_func4" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i32| { println!("host_func4: Found number {}", p); assert_eq!(p, -1); }), - "host_func5" => Function::new_native(&store, |p: i16| { + "host_func5" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i16| { println!("host_func5: Found number {}", p); assert_eq!(p, -1); }), - "host_func6" => Function::new_native(&store, |p: u16| { + "host_func6" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u16| { println!("host_func6: Found number {}", p); assert_eq!(p, u16::max_value()); }), - "host_func7" => Function::new_native(&store, |p: i8| { + "host_func7" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i8| { println!("host_func7: Found number {}", p); assert_eq!(p, -1); }), - "host_func8" => Function::new_native(&store, |p: u8| { + "host_func8" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u8| { println!("host_func8: Found number {}", p); assert_eq!(p, u8::max_value()); }), } }; - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&mut ctx, &module, &imports)?; - let f1: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func1")?; - let f2: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func2")?; - let f3: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func3")?; - let f4: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func4")?; - let f5: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func5")?; - let f6: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func6")?; - let f7: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func7")?; - let f8: TypedFunction<(), ()> = instance.exports.get_typed_function("call_host_func8")?; + let f1: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func1")?; + let f2: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func2")?; + let f3: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func3")?; + let f4: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func4")?; + let f5: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func5")?; + let f6: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func6")?; + let f7: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func7")?; + let f8: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut ctx, "call_host_func8")?; - f1.call()?; - f2.call()?; - f3.call()?; - f4.call()?; - f5.call()?; - f6.call()?; - f7.call()?; - f8.call()?; + f1.call(&mut ctx)?; + f2.call(&mut ctx)?; + f3.call(&mut ctx)?; + f4.call(&mut ctx)?; + f5.call(&mut ctx)?; + f6.call(&mut ctx)?; + f7.call(&mut ctx)?; + f8.call(&mut ctx)?; Ok(()) } diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs index 0878fb2bd96..c6024d3377d 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/sys_reference_types.rs @@ -4,6 +4,7 @@ mod sys { use std::collections::HashMap; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; + use wasmer::Context as WasmerContext; use wasmer::*; #[test] @@ -21,35 +22,36 @@ mod sys { (call_indirect $table (type $ret_i32_ty) (i32.const 0))) )"#; let module = Module::new(&store, wat)?; + #[derive(Clone, Debug)] + pub struct Env(Arc); + let env = Env(Arc::new(AtomicBool::new(false))); + let mut ctx = WasmerContext::new(&store, env); let imports = imports! { "env" => { - "func_ref_identity" => Function::new(&store, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |values| -> Result, _> { + "func_ref_identity" => Function::new(&mut ctx, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |_ctx: ContextMut, values: &[Value]| -> Result, _> { Ok(vec![values[0].clone()]) }) }, }; - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&mut ctx, &module, &imports)?; let f: &Function = instance.exports.get_function("run")?; - let results = f.call(&[]).unwrap(); + let results = f.call(&mut ctx, &[]).unwrap(); if let Value::FuncRef(fr) = &results[0] { assert!(fr.is_none()); } else { panic!("funcref not found!"); } - #[derive(Clone, Debug)] - pub struct Env(Arc); - let env = Env(Arc::new(AtomicBool::new(false))); - - let func_to_call = Function::new_native(&store, env.clone(), |env: &Env| -> i32 { - env.0.store(true, Ordering::SeqCst); + let func_to_call = Function::new_native(&mut ctx, |mut ctx: ContextMut| -> i32 { + ctx.data_mut().0.store(true, Ordering::SeqCst); 343 }); let call_set_value: &Function = instance.exports.get_function("call_set_value")?; - let results: Box<[Value]> = call_set_value.call(&[Value::FuncRef(Some(func_to_call))])?; - assert!(env.0.load(Ordering::SeqCst)); + let results: Box<[Value]> = + call_set_value.call(&mut ctx, &[Value::FuncRef(Some(func_to_call))])?; + assert!(ctx.data().0.load(Ordering::SeqCst)); assert_eq!(&*results, &[Value::I32(343)]); Ok(()) @@ -76,18 +78,21 @@ mod sys { (call $func_ref_call (ref.func $product))) )"#; let module = Module::new(&store, wat)?; - - fn func_ref_call(values: &[Value]) -> Result, RuntimeError> { + let mut ctx = WasmerContext::new(&store, ()); + fn func_ref_call( + mut ctx: ContextMut<()>, + values: &[Value], + ) -> Result, RuntimeError> { // TODO: look into `Box<[Value]>` being returned breakage let f = values[0].unwrap_funcref().as_ref().unwrap(); - let f: TypedFunction<(i32, i32), i32> = f.native()?; - Ok(vec![Value::I32(f.call(7, 9)?)]) + let f: TypedFunction<(i32, i32), i32> = f.native(&mut ctx)?; + Ok(vec![Value::I32(f.call(&mut ctx, 7, 9)?)]) } let imports = imports! { "env" => { "func_ref_call" => Function::new( - &store, + &mut ctx, FunctionType::new([Type::FuncRef], [Type::I32]), func_ref_call ), @@ -101,392 +106,394 @@ mod sys { }, }; - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&mut ctx, &module, &imports)?; { - fn sum(a: i32, b: i32) -> i32 { + fn sum(ctx: ContextMut<()>, a: i32, b: i32) -> i32 { a + b } - let sum_func = Function::new_native(&store, sum); + let sum_func = Function::new_native(&mut ctx, sum); let call_func: &Function = instance.exports.get_function("call_func")?; - let result = call_func.call(&[Value::FuncRef(Some(sum_func))])?; + let result = call_func.call(&mut ctx, &[Value::FuncRef(Some(sum_func))])?; assert_eq!(result[0].unwrap_i32(), 16); } { let f: TypedFunction<(), i32> = instance .exports - .get_typed_function("call_host_func_with_wasm_func")?; - let result = f.call()?; + .get_typed_function(&mut ctx, "call_host_func_with_wasm_func")?; + let result = f.call(&mut ctx)?; assert_eq!(result, 63); } Ok(()) } + /* + #[test] + fn extern_ref_passed_and_returned() -> Result<()> { + let store = Store::default(); + let mut ctx = WasmerContext::new(&store, ()); + let wat = r#"(module + (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) + (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) + (func $get_new_extern_ref (import "env" "get_new_extern_ref") (result externref)) + (func $get_new_extern_ref_native (import "env" "get_new_extern_ref_native") (result externref)) + + (func (export "run") (param) (result externref) + (call $extern_ref_identity (ref.null extern))) + (func (export "run_native") (param) (result externref) + (call $extern_ref_identity_native (ref.null extern))) + (func (export "get_hashmap") (param) (result externref) + (call $get_new_extern_ref)) + (func (export "get_hashmap_native") (param) (result externref) + (call $get_new_extern_ref_native)) + )"#; + let module = Module::new(&store, wat)?; + let imports = imports! { + "env" => { + "extern_ref_identity" => Function::new(&mut ctx, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |_ctx, values| -> Result, _> { + Ok(vec![values[0].clone()]) + }), + "extern_ref_identity_native" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, er: ExternRef| -> ExternRef { + er + }), + "get_new_extern_ref" => Function::new(&mut ctx, FunctionType::new([], [Type::ExternRef]), |_ctx, _| -> Result, _> { + let inner = + [("hello".to_string(), "world".to_string()), + ("color".to_string(), "orange".to_string())] + .iter() + .cloned() + .collect::>(); + let new_extern_ref = ExternRef::new(&mut ctx, inner); + Ok(vec![Value::ExternRef(new_extern_ref)]) + }), + "get_new_extern_ref_native" => Function::new_native(&mut ctx, |_ctx| -> ExternRef { + let inner = + [("hello".to_string(), "world".to_string()), + ("color".to_string(), "orange".to_string())] + .iter() + .cloned() + .collect::>(); + ExternRef::new(inner) + }) + }, + }; + + let instance = Instance::new(&module, &imports)?; + for run in &["run", "run_native"] { + let f: &Function = instance.exports.get_function(run)?; + let results = f.call(&[]).unwrap(); + if let Value::ExternRef(er) = &results[0] { + assert!(er.is_null()); + } else { + panic!("result is not an extern ref!"); + } - #[test] - fn extern_ref_passed_and_returned() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) - (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) - (func $get_new_extern_ref (import "env" "get_new_extern_ref") (result externref)) - (func $get_new_extern_ref_native (import "env" "get_new_extern_ref_native") (result externref)) - - (func (export "run") (param) (result externref) - (call $extern_ref_identity (ref.null extern))) - (func (export "run_native") (param) (result externref) - (call $extern_ref_identity_native (ref.null extern))) - (func (export "get_hashmap") (param) (result externref) - (call $get_new_extern_ref)) - (func (export "get_hashmap_native") (param) (result externref) - (call $get_new_extern_ref_native)) -)"#; - let module = Module::new(&store, wat)?; - let imports = imports! { - "env" => { - "extern_ref_identity" => Function::new(&store, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |values| -> Result, _> { - Ok(vec![values[0].clone()]) - }), - "extern_ref_identity_native" => Function::new_native(&store, |er: ExternRef| -> ExternRef { - er - }), - "get_new_extern_ref" => Function::new(&store, FunctionType::new([], [Type::ExternRef]), |_| -> Result, _> { - let inner = - [("hello".to_string(), "world".to_string()), - ("color".to_string(), "orange".to_string())] - .iter() - .cloned() - .collect::>(); - let new_extern_ref = ExternRef::new(inner); - Ok(vec![Value::ExternRef(new_extern_ref)]) - }), - "get_new_extern_ref_native" => Function::new_native(&store, || -> ExternRef { - let inner = - [("hello".to_string(), "world".to_string()), - ("color".to_string(), "orange".to_string())] - .iter() - .cloned() - .collect::>(); - ExternRef::new(inner) - }) - }, - }; - - let instance = Instance::new(&module, &imports)?; - for run in &["run", "run_native"] { - let f: &Function = instance.exports.get_function(run)?; - let results = f.call(&[]).unwrap(); - if let Value::ExternRef(er) = &results[0] { - assert!(er.is_null()); - } else { - panic!("result is not an extern ref!"); + let f: TypedFunction<(), ExternRef> = instance.exports.get_typed_function(run)?; + let result: ExternRef = f.call()?; + assert!(result.is_null()); } - let f: TypedFunction<(), ExternRef> = instance.exports.get_typed_function(run)?; - let result: ExternRef = f.call()?; - assert!(result.is_null()); - } + for get_hashmap in &["get_hashmap", "get_hashmap_native"] { + let f: &Function = instance.exports.get_function(get_hashmap)?; + let results = f.call(&[]).unwrap(); + if let Value::ExternRef(er) = &results[0] { + let inner: &HashMap = er.downcast().unwrap(); + assert_eq!(inner["hello"], "world"); + assert_eq!(inner["color"], "orange"); + } else { + panic!("result is not an extern ref!"); + } - for get_hashmap in &["get_hashmap", "get_hashmap_native"] { - let f: &Function = instance.exports.get_function(get_hashmap)?; - let results = f.call(&[]).unwrap(); - if let Value::ExternRef(er) = &results[0] { - let inner: &HashMap = er.downcast().unwrap(); + let f: TypedFunction<(), ExternRef> = + instance.exports.get_typed_function(get_hashmap)?; + + let result: ExternRef = f.call()?; + let inner: &HashMap = result.downcast().unwrap(); assert_eq!(inner["hello"], "world"); assert_eq!(inner["color"], "orange"); - } else { - panic!("result is not an extern ref!"); } - let f: TypedFunction<(), ExternRef> = - instance.exports.get_typed_function(get_hashmap)?; - - let result: ExternRef = f.call()?; - let inner: &HashMap = result.downcast().unwrap(); - assert_eq!(inner["hello"], "world"); - assert_eq!(inner["color"], "orange"); + Ok(()) } - Ok(()) - } - - #[test] - // TODO(reftypes): reenable this test - #[ignore] - fn extern_ref_ref_counting_basic() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (func (export "drop") (param $er externref) (result) - (drop (local.get $er))) -)"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; - let f: TypedFunction = instance.exports.get_typed_function("drop")?; - - let er = ExternRef::new(3u32); - f.call(er.clone())?; - - assert_eq!(er.downcast::().unwrap(), &3); - assert_eq!(er.strong_count(), 1); - - Ok(()) - } - - #[test] - fn refs_in_globals() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (global $er_global (export "er_global") (mut externref) (ref.null extern)) - (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) - (global $fr_immutable_global (export "fr_immutable_global") funcref (ref.func $hello)) - (func $hello (param) (result i32) - (i32.const 73)) -)"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; - { - let er_global: &Global = instance.exports.get_global("er_global")?; - - if let Value::ExternRef(er) = er_global.get() { - assert!(er.is_null()); - } else { - panic!("Did not find extern ref in the global"); - } - - er_global.set(Val::ExternRef(ExternRef::new(3u32)))?; - - if let Value::ExternRef(er) = er_global.get() { - assert_eq!(er.downcast::().unwrap(), &3); - assert_eq!(er.strong_count(), 1); - } else { - panic!("Did not find extern ref in the global"); - } + #[test] + // TODO(reftypes): reenable this test + #[ignore] + fn extern_ref_ref_counting_basic() -> Result<()> { + let store = Store::default(); + let wat = r#"(module + (func (export "drop") (param $er externref) (result) + (drop (local.get $er))) + )"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&module, &imports! {})?; + let f: TypedFunction = instance.exports.get_typed_function("drop")?; + + let er = ExternRef::new(3u32); + f.call(er.clone())?; + + assert_eq!(er.downcast::().unwrap(), &3); + assert_eq!(er.strong_count(), 1); + + Ok(()) } - { - let fr_global: &Global = instance.exports.get_global("fr_immutable_global")?; - - if let Value::FuncRef(Some(f)) = fr_global.get() { - let native_func: TypedFunction<(), u32> = f.native()?; - assert_eq!(native_func.call()?, 73); - } else { - panic!("Did not find non-null func ref in the global"); - } - } + #[test] + fn refs_in_globals() -> Result<()> { + let store = Store::default(); + let wat = r#"(module + (global $er_global (export "er_global") (mut externref) (ref.null extern)) + (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) + (global $fr_immutable_global (export "fr_immutable_global") funcref (ref.func $hello)) + (func $hello (param) (result i32) + (i32.const 73)) + )"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&module, &imports! {})?; + { + let er_global: &Global = instance.exports.get_global("er_global")?; + + if let Value::ExternRef(er) = er_global.get() { + assert!(er.is_null()); + } else { + panic!("Did not find extern ref in the global"); + } - { - let fr_global: &Global = instance.exports.get_global("fr_global")?; + er_global.set(Value::ExternRef(ExternRef::new(3u32)))?; - if let Value::FuncRef(None) = fr_global.get() { - } else { - panic!("Did not find a null func ref in the global"); + if let Value::ExternRef(er) = er_global.get() { + assert_eq!(er.downcast::().unwrap(), &3); + assert_eq!(er.strong_count(), 1); + } else { + panic!("Did not find extern ref in the global"); + } } - let f = Function::new_native(&store, |arg1: i32, arg2: i32| -> i32 { arg1 + arg2 }); + { + let fr_global: &Global = instance.exports.get_global("fr_immutable_global")?; - fr_global.set(Val::FuncRef(Some(f)))?; - - if let Value::FuncRef(Some(f)) = fr_global.get() { - let native: TypedFunction<(i32, i32), i32> = f.native()?; - assert_eq!(native.call(5, 7)?, 12); - } else { - panic!("Did not find extern ref in the global"); + if let Value::FuncRef(Some(f)) = fr_global.get() { + let native_func: TypedFunction<(), u32> = f.native()?; + assert_eq!(native_func.call()?, 73); + } else { + panic!("Did not find non-null func ref in the global"); + } } - } - Ok(()) - } + { + let fr_global: &Global = instance.exports.get_global("fr_global")?; - #[test] - fn extern_ref_ref_counting_table_basic() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (global $global (export "global") (mut externref) (ref.null extern)) - (table $table (export "table") 4 4 externref) - (func $insert (param $er externref) (param $idx i32) - (table.set $table (local.get $idx) (local.get $er))) - (func $intermediate (param $er externref) (param $idx i32) - (call $insert (local.get $er) (local.get $idx))) - (func $insert_into_table (export "insert_into_table") (param $er externref) (param $idx i32) (result externref) - (call $intermediate (local.get $er) (local.get $idx)) - (local.get $er)) -)"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; - - let f: TypedFunction<(ExternRef, i32), ExternRef> = - instance.exports.get_typed_function("insert_into_table")?; + if let Value::FuncRef(None) = fr_global.get() { + } else { + panic!("Did not find a null func ref in the global"); + } - let er = ExternRef::new(3usize); + let f = Function::new_native(&store, |arg1: i32, arg2: i32| -> i32 { arg1 + arg2 }); - let er = f.call(er, 1)?; - assert_eq!(er.strong_count(), 2); + fr_global.set(Value::FuncRef(Some(f)))?; - let table: &Table = instance.exports.get_table("table")?; + if let Value::FuncRef(Some(f)) = fr_global.get() { + let native: TypedFunction<(i32, i32), i32> = f.native()?; + assert_eq!(native.call(5, 7)?, 12); + } else { + panic!("Did not find extern ref in the global"); + } + } - { - let er2 = table.get(1).unwrap().externref().unwrap(); - assert_eq!(er2.strong_count(), 3); + Ok(()) } - assert_eq!(er.strong_count(), 2); - table.set(1, Val::ExternRef(ExternRef::null()))?; + #[test] + fn extern_ref_ref_counting_table_basic() -> Result<()> { + let store = Store::default(); + let wat = r#"(module + (global $global (export "global") (mut externref) (ref.null extern)) + (table $table (export "table") 4 4 externref) + (func $insert (param $er externref) (param $idx i32) + (table.set $table (local.get $idx) (local.get $er))) + (func $intermediate (param $er externref) (param $idx i32) + (call $insert (local.get $er) (local.get $idx))) + (func $insert_into_table (export "insert_into_table") (param $er externref) (param $idx i32) (result externref) + (call $intermediate (local.get $er) (local.get $idx)) + (local.get $er)) + )"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&module, &imports! {})?; + + let f: TypedFunction<(ExternRef, i32), ExternRef> = + instance.exports.get_typed_function("insert_into_table")?; - assert_eq!(er.strong_count(), 1); + let er = ExternRef::new(3usize); - Ok(()) - } + let er = f.call(er, 1)?; + assert_eq!(er.strong_count(), 2); - #[test] - // TODO(reftypes): reenable this test - #[ignore] - fn extern_ref_ref_counting_global_basic() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (global $global (export "global") (mut externref) (ref.null extern)) - (func $get_from_global (export "get_from_global") (result externref) - (drop (global.get $global)) - (global.get $global)) -)"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + let table: &Table = instance.exports.get_table("table")?; - let global: &Global = instance.exports.get_global("global")?; - { - let er = ExternRef::new(3usize); - global.set(Val::ExternRef(er.clone()))?; - assert_eq!(er.strong_count(), 2); - } - let get_from_global: TypedFunction<(), ExternRef> = - instance.exports.get_typed_function("get_from_global")?; + { + let er2 = table.get(1).unwrap().externref().unwrap(); + assert_eq!(er2.strong_count(), 3); + } - let er = get_from_global.call()?; - assert_eq!(er.strong_count(), 2); - global.set(Val::ExternRef(ExternRef::null()))?; - assert_eq!(er.strong_count(), 1); + assert_eq!(er.strong_count(), 2); + table.set(1, Value::ExternRef(ExternRef::null()))?; - Ok(()) - } + assert_eq!(er.strong_count(), 1); - #[test] - // TODO(reftypes): reenable this test - #[ignore] - fn extern_ref_ref_counting_traps() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (func $pass_er (export "pass_extern_ref") (param externref) - (local.get 0) - (unreachable)) -)"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + Ok(()) + } - let pass_extern_ref: TypedFunction = - instance.exports.get_typed_function("pass_extern_ref")?; + #[test] + // TODO(reftypes): reenable this test + #[ignore] + fn extern_ref_ref_counting_global_basic() -> Result<()> { + let store = Store::default(); + let wat = r#"(module + (global $global (export "global") (mut externref) (ref.null extern)) + (func $get_from_global (export "get_from_global") (result externref) + (drop (global.get $global)) + (global.get $global)) + )"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&module, &imports! {})?; + + let global: &Global = instance.exports.get_global("global")?; + { + let er = ExternRef::new(3usize); + global.set(Value::ExternRef(er.clone()))?; + assert_eq!(er.strong_count(), 2); + } + let get_from_global: TypedFunction<(), ExternRef> = + instance.exports.get_typed_function("get_from_global")?; - let er = ExternRef::new(3usize); - assert_eq!(er.strong_count(), 1); + let er = get_from_global.call()?; + assert_eq!(er.strong_count(), 2); + global.set(Value::ExternRef(ExternRef::null()))?; + assert_eq!(er.strong_count(), 1); - let result = pass_extern_ref.call(er.clone()); - assert!(result.is_err()); - assert_eq!(er.strong_count(), 1); + Ok(()) + } - Ok(()) - } + #[test] + // TODO(reftypes): reenable this test + #[ignore] + fn extern_ref_ref_counting_traps() -> Result<()> { + let store = Store::default(); + let wat = r#"(module + (func $pass_er (export "pass_extern_ref") (param externref) + (local.get 0) + (unreachable)) + )"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&module, &imports! {})?; + + let pass_extern_ref: TypedFunction = + instance.exports.get_typed_function("pass_extern_ref")?; - #[test] - fn extern_ref_ref_counting_table_instructions() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (table $table1 (export "table1") 2 12 externref) - (table $table2 (export "table2") 6 12 externref) - (func $grow_table_with_ref (export "grow_table_with_ref") (param $er externref) (param $size i32) (result i32) - (table.grow $table1 (local.get $er) (local.get $size))) - (func $fill_table_with_ref (export "fill_table_with_ref") (param $er externref) (param $start i32) (param $end i32) - (table.fill $table1 (local.get $start) (local.get $er) (local.get $end))) - (func $copy_into_table2 (export "copy_into_table2") - (table.copy $table2 $table1 (i32.const 0) (i32.const 0) (i32.const 4))) -)"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; - - let grow_table_with_ref: TypedFunction<(ExternRef, i32), i32> = - instance.exports.get_typed_function("grow_table_with_ref")?; - let fill_table_with_ref: TypedFunction<(ExternRef, i32, i32), ()> = - instance.exports.get_typed_function("fill_table_with_ref")?; - let copy_into_table2: TypedFunction<(), ()> = - instance.exports.get_typed_function("copy_into_table2")?; - let table1: &Table = instance.exports.get_table("table1")?; - let table2: &Table = instance.exports.get_table("table2")?; - - let er1 = ExternRef::new(3usize); - let er2 = ExternRef::new(5usize); - let er3 = ExternRef::new(7usize); - { - let result = grow_table_with_ref.call(er1.clone(), 0)?; - assert_eq!(result, 2); - assert_eq!(er1.strong_count(), 1); + let er = ExternRef::new(3usize); + assert_eq!(er.strong_count(), 1); - let result = grow_table_with_ref.call(er1.clone(), 10_000)?; - assert_eq!(result, -1); - assert_eq!(er1.strong_count(), 1); + let result = pass_extern_ref.call(er.clone()); + assert!(result.is_err()); + assert_eq!(er.strong_count(), 1); - let result = grow_table_with_ref.call(er1.clone(), 8)?; - assert_eq!(result, 2); - assert_eq!(er1.strong_count(), 9); + Ok(()) + } - for i in 2..10 { - let e = table1.get(i).unwrap().unwrap_externref(); - assert_eq!(*e.downcast::().unwrap(), 3); - assert_eq!(&e, &er1); + #[test] + fn extern_ref_ref_counting_table_instructions() -> Result<()> { + let store = Store::default(); + let wat = r#"(module + (table $table1 (export "table1") 2 12 externref) + (table $table2 (export "table2") 6 12 externref) + (func $grow_table_with_ref (export "grow_table_with_ref") (param $er externref) (param $size i32) (result i32) + (table.grow $table1 (local.get $er) (local.get $size))) + (func $fill_table_with_ref (export "fill_table_with_ref") (param $er externref) (param $start i32) (param $end i32) + (table.fill $table1 (local.get $start) (local.get $er) (local.get $end))) + (func $copy_into_table2 (export "copy_into_table2") + (table.copy $table2 $table1 (i32.const 0) (i32.const 0) (i32.const 4))) + )"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&module, &imports! {})?; + + let grow_table_with_ref: TypedFunction<(ExternRef, i32), i32> = + instance.exports.get_typed_function("grow_table_with_ref")?; + let fill_table_with_ref: TypedFunction<(ExternRef, i32, i32), ()> = + instance.exports.get_typed_function("fill_table_with_ref")?; + let copy_into_table2: TypedFunction<(), ()> = + instance.exports.get_typed_function("copy_into_table2")?; + let table1: &Table = instance.exports.get_table("table1")?; + let table2: &Table = instance.exports.get_table("table2")?; + + let er1 = ExternRef::new(3usize); + let er2 = ExternRef::new(5usize); + let er3 = ExternRef::new(7usize); + { + let result = grow_table_with_ref.call(er1.clone(), 0)?; + assert_eq!(result, 2); + assert_eq!(er1.strong_count(), 1); + + let result = grow_table_with_ref.call(er1.clone(), 10_000)?; + assert_eq!(result, -1); + assert_eq!(er1.strong_count(), 1); + + let result = grow_table_with_ref.call(er1.clone(), 8)?; + assert_eq!(result, 2); + assert_eq!(er1.strong_count(), 9); + + for i in 2..10 { + let e = table1.get(i).unwrap().unwrap_externref(); + assert_eq!(*e.downcast::().unwrap(), 3); + assert_eq!(&e, &er1); + } + assert_eq!(er1.strong_count(), 9); } - assert_eq!(er1.strong_count(), 9); - } - { - fill_table_with_ref.call(er2.clone(), 0, 2)?; - assert_eq!(er2.strong_count(), 3); - } + { + fill_table_with_ref.call(er2.clone(), 0, 2)?; + assert_eq!(er2.strong_count(), 3); + } - { - table2.set(0, Val::ExternRef(er3.clone()))?; - table2.set(1, Val::ExternRef(er3.clone()))?; - table2.set(2, Val::ExternRef(er3.clone()))?; - table2.set(3, Val::ExternRef(er3.clone()))?; - table2.set(4, Val::ExternRef(er3.clone()))?; - assert_eq!(er3.strong_count(), 6); - } + { + table2.set(0, Value::ExternRef(er3.clone()))?; + table2.set(1, Value::ExternRef(er3.clone()))?; + table2.set(2, Value::ExternRef(er3.clone()))?; + table2.set(3, Value::ExternRef(er3.clone()))?; + table2.set(4, Value::ExternRef(er3.clone()))?; + assert_eq!(er3.strong_count(), 6); + } - { - copy_into_table2.call()?; - assert_eq!(er3.strong_count(), 2); - assert_eq!(er2.strong_count(), 5); - assert_eq!(er1.strong_count(), 11); - for i in 1..5 { - let e = table2.get(i).unwrap().unwrap_externref(); - let value = e.downcast::().unwrap(); - match i { - 0 | 1 => assert_eq!(*value, 5), - 4 => assert_eq!(*value, 7), - _ => assert_eq!(*value, 3), + { + copy_into_table2.call()?; + assert_eq!(er3.strong_count(), 2); + assert_eq!(er2.strong_count(), 5); + assert_eq!(er1.strong_count(), 11); + for i in 1..5 { + let e = table2.get(i).unwrap().unwrap_externref(); + let value = e.downcast::().unwrap(); + match i { + 0 | 1 => assert_eq!(*value, 5), + 4 => assert_eq!(*value, 7), + _ => assert_eq!(*value, 3), + } } } - } - { - for i in 0..table1.size() { - table1.set(i, Val::ExternRef(ExternRef::null()))?; - } - for i in 0..table2.size() { - table2.set(i, Val::ExternRef(ExternRef::null()))?; + { + for i in 0..table1.size() { + table1.set(i, Value::ExternRef(ExternRef::null()))?; + } + for i in 0..table2.size() { + table2.set(i, Value::ExternRef(ExternRef::null()))?; + } } - } - assert_eq!(er1.strong_count(), 1); - assert_eq!(er2.strong_count(), 1); - assert_eq!(er3.strong_count(), 1); + assert_eq!(er1.strong_count(), 1); + assert_eq!(er2.strong_count(), 1); + assert_eq!(er3.strong_count(), 1); - Ok(()) - } + Ok(()) + } + */ } diff --git a/lib/derive/tests/basic.rs b/lib/derive/tests/basic.rs deleted file mode 100644 index 7b15df4e3ef..00000000000 --- a/lib/derive/tests/basic.rs +++ /dev/null @@ -1,119 +0,0 @@ -#![allow(dead_code)] - -use wasmer::{Function, Global, LazyInit, Memory, Table, TypedFunction, WasmerEnv}; - -#[derive(WasmerEnv, Clone)] -struct MyEnv { - num: u32, - nums: Vec, -} - -fn impls_wasmer_env() -> bool { - true -} - -#[test] -fn test_derive() { - let _my_env = MyEnv { - num: 3, - nums: vec![1, 2, 3], - }; - assert!(impls_wasmer_env::()); -} - -#[derive(WasmerEnv, Clone)] -struct MyEnvWithMemory { - num: u32, - nums: Vec, - #[wasmer(export)] - memory: LazyInit, -} - -#[derive(WasmerEnv, Clone)] -struct MyEnvWithFuncs { - num: u32, - nums: Vec, - #[wasmer(export)] - memory: LazyInit, - #[wasmer(export)] - sum: LazyInit>, -} - -#[derive(WasmerEnv, Clone)] -struct MyEnvWithEverything { - num: u32, - nums: Vec, - #[wasmer(export)] - memory: LazyInit, - #[wasmer(export)] - sum: LazyInit>, - #[wasmer(export)] - multiply: LazyInit, - #[wasmer(export)] - counter: LazyInit, - #[wasmer(export)] - functions: LazyInit
, -} - -#[derive(WasmerEnv, Clone)] -struct MyEnvWithLifetime<'a> { - name: &'a str, - #[wasmer(export(name = "memory"))] - memory: LazyInit, -} - -#[derive(WasmerEnv, Clone)] -struct MyUnitStruct; - -#[derive(WasmerEnv, Clone)] -struct MyTupleStruct(u32); - -#[derive(WasmerEnv, Clone)] -struct MyTupleStruct2(u32, u32); - -#[derive(WasmerEnv, Clone)] -struct MyTupleStructWithAttribute(#[wasmer(export(name = "memory"))] LazyInit, u32); - -#[test] -fn test_derive_with_attribute() { - assert!(impls_wasmer_env::()); - assert!(impls_wasmer_env::()); - assert!(impls_wasmer_env::()); - assert!(impls_wasmer_env::()); - assert!(impls_wasmer_env::()); - assert!(impls_wasmer_env::()); - assert!(impls_wasmer_env::()); - assert!(impls_wasmer_env::()); -} - -#[derive(WasmerEnv, Clone)] -struct StructWithOptionalField { - #[wasmer(export(optional = true))] - memory: LazyInit, - #[wasmer(export(optional = true, name = "real_memory"))] - memory2: LazyInit, - #[wasmer(export(optional = false))] - memory3: LazyInit, -} - -#[test] -fn test_derive_with_optional() { - assert!(impls_wasmer_env::()); -} - -#[derive(WasmerEnv, Clone)] -struct StructWithAliases { - #[wasmer(export(alias = "_memory"))] - memory: LazyInit, - #[wasmer(export(alias = "_real_memory", optional = true, name = "real_memory"))] - memory2: LazyInit, - #[wasmer(export(alias = "_memory3", alias = "__memory3"))] - memory3: LazyInit, - #[wasmer(export(alias = "_memory3", name = "memory4", alias = "__memory3"))] - memory4: LazyInit, -} - -#[test] -fn test_derive_with_aliases() { - assert!(impls_wasmer_env::()); -} diff --git a/lib/types/src/value.rs b/lib/types/src/value.rs index 8e822d79146..2347832cc03 100644 --- a/lib/types/src/value.rs +++ b/lib/types/src/value.rs @@ -13,6 +13,7 @@ pub union RawValue { pub u64: u64, pub f32: f32, pub f64: f64, + pub i128: i128, pub u128: u128, pub funcref: usize, pub externref: usize, @@ -33,6 +34,32 @@ impl fmt::Debug for RawValue { } } +macro_rules! partial_eq { + ($($t:ty => $f:tt),*) => ($( + impl PartialEq<$t> for RawValue { + fn eq(&self, o: &$t) -> bool { + unsafe { self.$f == *o } + } + } + )*) +} +partial_eq! { + i32 => i32, + u32 => u32, + i64 => i64, + u64 => u64, + f32 => f32, + f64 => f64, + i128 => i128, + u128 => u128 +} + +impl PartialEq for RawValue { + fn eq(&self, o: &Self) -> bool { + unsafe { self.u128 == o.u128 } + } +} + /// Trait for a Value type. A Value type is a type that is always valid and may /// be safely copied. /// diff --git a/tests/compilers/imports.rs b/tests/compilers/imports.rs index 8c8ab7db07c..232103d0a86 100644 --- a/tests/compilers/imports.rs +++ b/tests/compilers/imports.rs @@ -8,6 +8,8 @@ use std::sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, Arc, }; +use wasmer::Context as WasmerContext; +use wasmer::Type as ValueType; use wasmer::*; fn get_module(store: &Store) -> Result { @@ -47,27 +49,26 @@ fn get_module(store: &Store) -> Result { fn dynamic_function(config: crate::Config) -> Result<()> { let store = config.store(); let module = get_module(&store)?; + let mut ctx = WasmerContext::new(&store, ()); static HITS: AtomicUsize = AtomicUsize::new(0); - Instance::new( - &module, - &imports! { - "host" => { - "0" => Function::new(&store, FunctionType::new(vec![], vec![]), |_values| { + let imports = imports! { + "host" => { + "0" => Function::new(&mut ctx, FunctionType::new(vec![], vec![]), |_ctx, _values| { assert_eq!(HITS.fetch_add(1, SeqCst), 0); Ok(vec![]) }), - "1" => Function::new(&store, FunctionType::new(vec![ValType::I32], vec![ValType::I32]), |values| { + "1" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32], vec![ValueType::I32]), |_ctx, values| { assert_eq!(values[0], Value::I32(0)); assert_eq!(HITS.fetch_add(1, SeqCst), 1); Ok(vec![Value::I32(1)]) }), - "2" => Function::new(&store, FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), |values| { + "2" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32, ValueType::I64], vec![]), |_ctx, values| { assert_eq!(values[0], Value::I32(2)); assert_eq!(values[1], Value::I64(3)); assert_eq!(HITS.fetch_add(1, SeqCst), 2); Ok(vec![]) }), - "3" => Function::new(&store, FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), |values| { + "3" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32, ValueType::I64, ValueType::I32, ValueType::F32, ValueType::F64], vec![]), |_ctx, values| { assert_eq!(values[0], Value::I32(100)); assert_eq!(values[1], Value::I64(200)); assert_eq!(values[2], Value::I32(300)); @@ -76,9 +77,9 @@ fn dynamic_function(config: crate::Config) -> Result<()> { assert_eq!(HITS.fetch_add(1, SeqCst), 3); Ok(vec![]) }), - }, - }, - )?; + } + }; + Instance::new(&mut ctx, &module, &imports)?; assert_eq!(HITS.swap(0, SeqCst), 4); Ok(()) } @@ -88,7 +89,7 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { let store = config.store(); let module = get_module(&store)?; - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env { counter: Arc, } @@ -103,38 +104,69 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { let env: Env = Env { counter: Arc::new(AtomicUsize::new(0)), }; + let mut ctx = WasmerContext::new(&store, env); + let f0 = Function::new( + &mut ctx, + FunctionType::new(vec![], vec![]), + |ctx, _values| { + assert_eq!(ctx.data().fetch_add(1, SeqCst), 0); + Ok(vec![]) + }, + ); + let f1 = Function::new( + &mut ctx, + FunctionType::new(vec![ValueType::I32], vec![ValueType::I32]), + |ctx, values| { + assert_eq!(values[0], Value::I32(0)); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 1); + Ok(vec![Value::I32(1)]) + }, + ); + let f2 = Function::new( + &mut ctx, + FunctionType::new(vec![ValueType::I32, ValueType::I64], vec![]), + |ctx, values| { + assert_eq!(values[0], Value::I32(2)); + assert_eq!(values[1], Value::I64(3)); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 2); + Ok(vec![]) + }, + ); + let f3 = Function::new( + &mut ctx, + FunctionType::new( + vec![ + ValueType::I32, + ValueType::I64, + ValueType::I32, + ValueType::F32, + ValueType::F64, + ], + vec![], + ), + |ctx, values| { + assert_eq!(values[0], Value::I32(100)); + assert_eq!(values[1], Value::I64(200)); + assert_eq!(values[2], Value::I32(300)); + assert_eq!(values[3], Value::F32(400.0)); + assert_eq!(values[4], Value::F64(500.0)); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 3); + Ok(vec![]) + }, + ); Instance::new( + &mut ctx, &module, &imports! { "host" => { - "0" => Function::new_with_env(&store, FunctionType::new(vec![], vec![]), env.clone(), |env, _values| { - assert_eq!(env.fetch_add(1, SeqCst), 0); - Ok(vec![]) - }), - "1" => Function::new_with_env(&store, FunctionType::new(vec![ValType::I32], vec![ValType::I32]), env.clone(), |env, values| { - assert_eq!(values[0], Value::I32(0)); - assert_eq!(env.fetch_add(1, SeqCst), 1); - Ok(vec![Value::I32(1)]) - }), - "2" => Function::new_with_env(&store, FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), env.clone(), |env, values| { - assert_eq!(values[0], Value::I32(2)); - assert_eq!(values[1], Value::I64(3)); - assert_eq!(env.fetch_add(1, SeqCst), 2); - Ok(vec![]) - }), - "3" => Function::new_with_env(&store, FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), env.clone(), |env, values| { - assert_eq!(values[0], Value::I32(100)); - assert_eq!(values[1], Value::I64(200)); - assert_eq!(values[2], Value::I32(300)); - assert_eq!(values[3], Value::F32(400.0)); - assert_eq!(values[4], Value::F64(500.0)); - assert_eq!(env.fetch_add(1, SeqCst), 3); - Ok(vec![]) - }), + "0" => f0, + "1" => f1, + "2" => f2, + "3" => f3, }, }, )?; - assert_eq!(env.load(SeqCst), 4); + assert_eq!(ctx.data_mut().load(SeqCst), 4); Ok(()) } @@ -145,31 +177,40 @@ fn static_function(config: crate::Config) -> Result<()> { let module = get_module(&store)?; static HITS: AtomicUsize = AtomicUsize::new(0); + let mut ctx = WasmerContext::new(&store, ()); + let f0 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + assert_eq!(HITS.fetch_add(1, SeqCst), 0); + }); + let f1 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, x: i32| -> i32 { + assert_eq!(x, 0); + assert_eq!(HITS.fetch_add(1, SeqCst), 1); + 1 + }); + let f2 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, x: i32, y: i64| { + assert_eq!(x, 2); + assert_eq!(y, 3); + assert_eq!(HITS.fetch_add(1, SeqCst), 2); + }); + let f3 = Function::new_native( + &mut ctx, + |_ctx: ContextMut<_>, a: i32, b: i64, c: i32, d: f32, e: f64| { + assert_eq!(a, 100); + assert_eq!(b, 200); + assert_eq!(c, 300); + assert_eq!(d, 400.0); + assert_eq!(e, 500.0); + assert_eq!(HITS.fetch_add(1, SeqCst), 3); + }, + ); Instance::new( + &mut ctx, &module, &imports! { "host" => { - "0" => Function::new_native(&store, || { - assert_eq!(HITS.fetch_add(1, SeqCst), 0); - }), - "1" => Function::new_native(&store, |x: i32| -> i32 { - assert_eq!(x, 0); - assert_eq!(HITS.fetch_add(1, SeqCst), 1); - 1 - }), - "2" => Function::new_native(&store, |x: i32, y: i64| { - assert_eq!(x, 2); - assert_eq!(y, 3); - assert_eq!(HITS.fetch_add(1, SeqCst), 2); - }), - "3" => Function::new_native(&store, |a: i32, b: i64, c: i32, d: f32, e: f64| { - assert_eq!(a, 100); - assert_eq!(b, 200); - assert_eq!(c, 300); - assert_eq!(d, 400.0); - assert_eq!(e, 500.0); - assert_eq!(HITS.fetch_add(1, SeqCst), 3); - }), + "0" => f0, + "1" => f1, + "2" => f2, + "3" => f3, }, }, )?; @@ -184,31 +225,43 @@ fn static_function_with_results(config: crate::Config) -> Result<()> { let module = get_module(&store)?; static HITS: AtomicUsize = AtomicUsize::new(0); + let mut ctx = WasmerContext::new(&store, ()); + let f0 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + assert_eq!(HITS.fetch_add(1, SeqCst), 0); + }); + let f1 = Function::new_native( + &mut ctx, + |_ctx: ContextMut<_>, x: i32| -> Result { + assert_eq!(x, 0); + assert_eq!(HITS.fetch_add(1, SeqCst), 1); + Ok(1) + }, + ); + let f2 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, x: i32, y: i64| { + assert_eq!(x, 2); + assert_eq!(y, 3); + assert_eq!(HITS.fetch_add(1, SeqCst), 2); + }); + let f3 = Function::new_native( + &mut ctx, + |_ctx: ContextMut<_>, a: i32, b: i64, c: i32, d: f32, e: f64| { + assert_eq!(a, 100); + assert_eq!(b, 200); + assert_eq!(c, 300); + assert_eq!(d, 400.0); + assert_eq!(e, 500.0); + assert_eq!(HITS.fetch_add(1, SeqCst), 3); + }, + ); Instance::new( + &mut ctx, &module, &imports! { "host" => { - "0" => Function::new_native(&store, || { - assert_eq!(HITS.fetch_add(1, SeqCst), 0); - }), - "1" => Function::new_native(&store, |x: i32| -> Result { - assert_eq!(x, 0); - assert_eq!(HITS.fetch_add(1, SeqCst), 1); - Ok(1) - }), - "2" => Function::new_native(&store, |x: i32, y: i64| { - assert_eq!(x, 2); - assert_eq!(y, 3); - assert_eq!(HITS.fetch_add(1, SeqCst), 2); - }), - "3" => Function::new_native(&store, |a: i32, b: i64, c: i32, d: f32, e: f64| { - assert_eq!(a, 100); - assert_eq!(b, 200); - assert_eq!(c, 300); - assert_eq!(d, 400.0); - assert_eq!(e, 500.0); - assert_eq!(HITS.fetch_add(1, SeqCst), 3); - }), + "0" => f0, + "1" => f1, + "2" => f2, + "3" => f3, }, }, )?; @@ -221,7 +274,7 @@ fn static_function_with_env(config: crate::Config) -> Result<()> { let store = config.store(); let module = get_module(&store)?; - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env(Arc); impl std::ops::Deref for Env { @@ -232,35 +285,44 @@ fn static_function_with_env(config: crate::Config) -> Result<()> { } let env: Env = Env(Arc::new(AtomicUsize::new(0))); + let mut ctx = WasmerContext::new(&store, env); + let f0 = Function::new_native(&mut ctx, |ctx: ContextMut| { + assert_eq!(ctx.data().fetch_add(1, SeqCst), 0); + }); + let f1 = Function::new_native(&mut ctx, |ctx: ContextMut, x: i32| -> i32 { + assert_eq!(x, 0); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 1); + 1 + }); + let f2 = Function::new_native(&mut ctx, |ctx: ContextMut, x: i32, y: i64| { + assert_eq!(x, 2); + assert_eq!(y, 3); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 2); + }); + let f3 = Function::new_native( + &mut ctx, + |ctx: ContextMut, a: i32, b: i64, c: i32, d: f32, e: f64| { + assert_eq!(a, 100); + assert_eq!(b, 200); + assert_eq!(c, 300); + assert_eq!(d, 400.0); + assert_eq!(e, 500.0); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 3); + }, + ); Instance::new( + &mut ctx, &module, &imports! { "host" => { - "0" => Function::new_native_with_env(&store, env.clone(), |env: &Env| { - assert_eq!(env.fetch_add(1, SeqCst), 0); - }), - "1" => Function::new_native_with_env(&store, env.clone(), |env: &Env, x: i32| -> i32 { - assert_eq!(x, 0); - assert_eq!(env.fetch_add(1, SeqCst), 1); - 1 - }), - "2" => Function::new_native_with_env(&store, env.clone(), |env: &Env, x: i32, y: i64| { - assert_eq!(x, 2); - assert_eq!(y, 3); - assert_eq!(env.fetch_add(1, SeqCst), 2); - }), - "3" => Function::new_native_with_env(&store, env.clone(), |env: &Env, a: i32, b: i64, c: i32, d: f32, e: f64| { - assert_eq!(a, 100); - assert_eq!(b, 200); - assert_eq!(c, 300); - assert_eq!(d, 400.0); - assert_eq!(e, 500.0); - assert_eq!(env.fetch_add(1, SeqCst), 3); - }), + "0" => f0, + "1" => f1, + "2" => f2, + "3" => f3, }, }, )?; - assert_eq!(env.load(SeqCst), 4); + assert_eq!(ctx.data_mut().load(SeqCst), 4); Ok(()) } @@ -277,14 +339,19 @@ fn static_function_that_fails(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &wat)?; - + let mut ctx = WasmerContext::new(&store, ()); + let f0 = Function::new_native( + &mut ctx, + |_ctx: ContextMut<_>| -> Result { + Err(RuntimeError::new("oops")) + }, + ); let result = Instance::new( + &mut ctx, &module, &imports! { "host" => { - "0" => Function::new_native(&store, || -> Result { - Err(RuntimeError::new("oops")) - }), + "0" => f0, }, }, ); @@ -321,28 +388,34 @@ fn dynamic_function_with_env_wasmer_env_init_works(config: crate::Config) -> Res let module = get_module2(&store)?; #[allow(dead_code)] - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env { - #[wasmer(export)] - memory: LazyInit, + memory: Option, } - let env: Env = Env { - memory: LazyInit::default(), - }; + let env: Env = Env { memory: None }; + let mut ctx = WasmerContext::new(&store, env); + let f0 = Function::new( + &mut ctx, + FunctionType::new(vec![], vec![]), + |ctx, _values| { + assert!(ctx.data().memory.as_ref().is_some()); + Ok(vec![]) + }, + ); let instance = Instance::new( + &mut ctx, &module, &imports! { "host" => { - "fn" => Function::new_with_env(&store, FunctionType::new(vec![], vec![]), env, |env, _values| { - assert!(env.memory_ref().is_some()); - Ok(vec![]) - }), + "fn" => f0, }, }, )?; - let f: TypedFunction<(), ()> = instance.exports.get_typed_function("main")?; - f.call()?; + let memory = instance.exports.get_memory("memory")?; + ctx.data_mut().memory = Some(memory.clone()); + let f: TypedFunction<(), ()> = instance.exports.get_typed_function(&ctx, "main")?; + f.call(&mut ctx)?; Ok(()) } @@ -354,40 +427,42 @@ fn multi_use_host_fn_manages_memory_correctly(config: crate::Config) -> Result<( #[allow(dead_code)] #[derive(Clone)] struct Env { - memory: LazyInit, + memory: Option, } - impl WasmerEnv for Env { + /* impl WasmerEnv for Env { fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> { let memory = instance.exports.get_memory("memory")?.clone(); self.memory.initialize(memory); Ok(()) } - } + }*/ - let env: Env = Env { - memory: LazyInit::default(), - }; - fn host_fn(env: &Env) { - assert!(env.memory.get_ref().is_some()); + let env: Env = Env { memory: None }; + let mut ctx = WasmerContext::new(&store, env); + fn host_fn(ctx: ContextMut) { + assert!(ctx.data().memory.is_some()); println!("Hello, world!"); } - let imports = imports! { "host" => { - "fn" => Function::new_native_with_env(&store, env, host_fn), + "fn" => Function::new_native(&mut ctx, host_fn), }, }; - let instance1 = Instance::new(&module, &imports)?; - let instance2 = Instance::new(&module, &imports)?; + let instance1 = Instance::new(&mut ctx, &module, &imports)?; + let instance2 = Instance::new(&mut ctx, &module, &imports)?; { - let f1: TypedFunction<(), ()> = instance1.exports.get_typed_function("main")?; - f1.call()?; + let f1: TypedFunction<(), ()> = instance1.exports.get_typed_function(&mut ctx, "main")?; + let memory = instance1.exports.get_memory("memory")?; + ctx.data_mut().memory = Some(memory.clone()); + f1.call(&mut ctx)?; } drop(instance1); { - let f2: TypedFunction<(), ()> = instance2.exports.get_typed_function("main")?; - f2.call()?; + let f2: TypedFunction<(), ()> = instance2.exports.get_typed_function(&mut ctx, "main")?; + let memory = instance2.exports.get_memory("memory")?; + ctx.data_mut().memory = Some(memory.clone()); + f2.call(&mut ctx)?; } drop(instance2); Ok(()) @@ -396,14 +471,14 @@ fn multi_use_host_fn_manages_memory_correctly(config: crate::Config) -> Result<( #[compiler_test(imports)] fn instance_local_memory_lifetime(config: crate::Config) -> Result<()> { let store = config.store(); - + let mut ctx = WasmerContext::new(&store, ()); let memory: Memory = { let wat = r#"(module (memory $mem 1) (export "memory" (memory $mem)) )"#; let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + let instance = Instance::new(&mut ctx, &module, &imports! {})?; instance.exports.get_memory("memory")?.clone() }; @@ -424,11 +499,13 @@ fn instance_local_memory_lifetime(config: crate::Config) -> Result<()> { "memory" => memory, }, }; - let instance = Instance::new(&module, &imports)?; - let set_at: TypedFunction<(i32, i32), ()> = instance.exports.get_typed_function("set_at")?; - let get_at: TypedFunction = instance.exports.get_typed_function("get_at")?; - set_at.call(200, 123)?; - assert_eq!(get_at.call(200)?, 123); + let instance = Instance::new(&mut ctx, &module, &imports)?; + let set_at: TypedFunction<(i32, i32), ()> = + instance.exports.get_typed_function(&mut ctx, "set_at")?; + let get_at: TypedFunction = + instance.exports.get_typed_function(&mut ctx, "get_at")?; + set_at.call(&mut ctx, 200, 123)?; + assert_eq!(get_at.call(&mut ctx, 200)?, 123); Ok(()) } diff --git a/tests/compilers/issues.rs b/tests/compilers/issues.rs index dcb63c6c207..07064cc95ca 100644 --- a/tests/compilers/issues.rs +++ b/tests/compilers/issues.rs @@ -1,5 +1,6 @@ //! This file is mainly to assure specific issues are working well use anyhow::Result; +use wasmer::Context as WasmerContext; use wasmer::*; /// Corruption of WasmerEnv when using call indirect. @@ -12,22 +13,19 @@ use wasmer::*; fn issue_2329(mut config: crate::Config) -> Result<()> { let store = config.store(); - #[derive(Clone, Default, WasmerEnv)] + #[derive(Clone, Default)] pub struct Env { - #[wasmer(export)] - memory: LazyInit, + memory: Option, } impl Env { pub fn new() -> Self { - Self { - memory: LazyInit::new(), - } + Self { memory: None } } } - pub fn read_memory(env: &Env, guest_ptr: u32) -> u32 { - dbg!(env.memory_ref()); + pub fn read_memory(ctx: ContextMut, guest_ptr: u32) -> u32 { + dbg!(ctx.data().memory.as_ref()); dbg!(guest_ptr); 0 } @@ -63,36 +61,34 @@ fn issue_2329(mut config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; let env = Env::new(); + let mut ctx = WasmerContext::new(&store, env); let imports: Imports = imports! { "env" => { - "__read_memory" => Function::new_native_with_env( - &store, - env, + "__read_memory" => Function::new_native( + &mut ctx, read_memory ), } }; - let instance = Instance::new(&module, &imports)?; - instance.exports.get_function("read_memory")?.call(&[])?; + let instance = Instance::new(&mut ctx, &module, &imports)?; + instance + .exports + .get_function("read_memory")? + .call(&mut ctx, &[])?; Ok(()) } #[compiler_test(issues)] fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { let store = config.store(); - let memory = Memory::new( - &store, - MemoryType::new(Pages(1024), Some(Pages(2048)), false), - ) - .unwrap(); - #[derive(Clone, WasmerEnv)] + #[derive(Clone)] pub struct Env { - memory: Memory, + memory: Option, } pub fn banana( - env: &Env, + mut ctx: ContextMut, a: u64, b: u64, c: u64, @@ -104,23 +100,24 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { ) -> u64 { println!("{:?}", (a, b, c, d, e, f, g, h)); let mut buf = vec![0; d as usize]; - env.memory.read(e, &mut buf).unwrap(); + let memory = ctx.data().memory.as_ref().unwrap(); + memory.read(&ctx, e, &mut buf).unwrap(); let input_string = std::str::from_utf8(&buf).unwrap(); assert_eq!(input_string, "bananapeach"); 0 } - pub fn mango(env: &Env, a: u64) {} + pub fn mango(ctx: ContextMut, a: u64) {} - pub fn chaenomeles(env: &Env, a: u64) -> u64 { + pub fn chaenomeles(ctx: ContextMut, a: u64) -> u64 { 0 } - pub fn peach(env: &Env, a: u64, b: u64) -> u64 { + pub fn peach(ctx: ContextMut, a: u64, b: u64) -> u64 { 0 } - pub fn gas(env: &Env, a: u32) {} + pub fn gas(ctx: ContextMut, a: u32) {} let wat = r#" (module @@ -189,32 +186,28 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let env = Env { - memory: memory.clone(), - }; + let env = Env { memory: None }; + let mut ctx = WasmerContext::new(&store, env); + let memory = Memory::new( + &mut ctx, + MemoryType::new(Pages(1024), Some(Pages(2048)), false), + ) + .unwrap(); + ctx.data_mut().memory = Some(memory.clone()); let mut exports = Exports::new(); exports.insert("memory", memory); - exports.insert( - "banana", - Function::new_native_with_env(&store, env.clone(), banana), - ); - exports.insert( - "peach", - Function::new_native_with_env(&store, env.clone(), peach), - ); - exports.insert( - "chaenomeles", - Function::new_native_with_env(&store, env.clone(), chaenomeles), - ); - exports.insert( - "mango", - Function::new_native_with_env(&store, env.clone(), mango), - ); - exports.insert("gas", Function::new_native_with_env(&store, env, gas)); + exports.insert("banana", Function::new_native(&mut ctx, banana)); + exports.insert("peach", Function::new_native(&mut ctx, peach)); + exports.insert("chaenomeles", Function::new_native(&mut ctx, chaenomeles)); + exports.insert("mango", Function::new_native(&mut ctx, mango)); + exports.insert("gas", Function::new_native(&mut ctx, gas)); let mut imports = Imports::new(); imports.register_namespace("env", exports); - let instance = Instance::new(&module, &imports)?; - instance.exports.get_function("repro")?.call(&[])?; + let instance = Instance::new(&mut ctx, &module, &imports)?; + instance + .exports + .get_function("repro")? + .call(&mut ctx, &[])?; Ok(()) } @@ -251,8 +244,9 @@ fn regression_gpr_exhaustion_for_calls(mut config: crate::Config) -> Result<()> i32.const 0) (table (;0;) 1 1 funcref)) "#; + let mut ctx = WasmerContext::new(&store, ()); let module = Module::new(&store, wat)?; let imports: Imports = imports! {}; - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&mut ctx, &module, &imports)?; Ok(()) } diff --git a/tests/compilers/metering.rs b/tests/compilers/metering.rs index 518552412f7..faf43e3ee55 100644 --- a/tests/compilers/metering.rs +++ b/tests/compilers/metering.rs @@ -3,6 +3,7 @@ use wasmer_middlewares::Metering; use std::sync::Arc; use wasmer::wasmparser::Operator; +use wasmer::Context as WasmerContext; use wasmer::*; fn cost_always_one(_: &Operator) -> u64 { @@ -19,14 +20,15 @@ fn run_add_with_limit(mut config: crate::Config, limit: u64) -> Result<()> { (i32.add (local.get 0) (local.get 1))) )"#; - let module = Module::new(&store, wat).unwrap(); + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let module = Module::new(&store, wat).unwrap(); + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; - f.call(4, 6)?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; + f.call(&mut ctx, 4, 6)?; Ok(()) } @@ -51,13 +53,14 @@ fn run_loop(mut config: crate::Config, limit: u64, iter_count: i32) -> Result<() ) )"#; let module = Module::new(&store, wat).unwrap(); + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction = instance.exports.get_typed_function("test")?; - f.call(iter_count)?; + let f: TypedFunction = instance.exports.get_typed_function(&mut ctx, "test")?; + f.call(&mut ctx, iter_count)?; Ok(()) } @@ -152,17 +155,19 @@ fn complex_loop(mut config: crate::Config) -> Result<()> { .middlewares .push(Arc::new(Metering::new(100, cost_always_one))); let store = config.store(); + let mut ctx = WasmerContext::new(&store, ()); let module = Module::new(&store, WAT).unwrap(); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add_to")?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut ctx, "add_to")?; // FIXME: Since now a metering error is signaled with an `unreachable`, it is impossible to verify // the error type. Fix this later. - f.call(10_000_000, 4).unwrap_err(); + f.call(&mut ctx, 10_000_000, 4).unwrap_err(); Ok(()) } diff --git a/tests/compilers/middlewares.rs b/tests/compilers/middlewares.rs index 0690a27c065..700051da7b7 100644 --- a/tests/compilers/middlewares.rs +++ b/tests/compilers/middlewares.rs @@ -2,6 +2,7 @@ use anyhow::Result; use std::sync::Arc; use wasmer::wasmparser::Operator; +use wasmer::Context as WasmerContext; use wasmer::*; #[derive(Debug)] @@ -99,13 +100,14 @@ fn middleware_basic(mut config: crate::Config) -> Result<()> { (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; - let result = f.call(4, 6)?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; + let result = f.call(&mut ctx, 4, 6)?; assert_eq!(result, 24); Ok(()) } @@ -122,13 +124,13 @@ fn middleware_one_to_multi(mut config: crate::Config) -> Result<()> { (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); - + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; - let result = f.call(4, 6)?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; + let result = f.call(&mut ctx, 4, 6)?; assert_eq!(result, 25); Ok(()) } @@ -146,13 +148,14 @@ fn middleware_multi_to_one(mut config: crate::Config) -> Result<()> { (i32.mul)) )"#; let module = Module::new(&store, wat).unwrap(); - + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("testfunc")?; - let result = f.call(10, 20)?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut ctx, "testfunc")?; + let result = f.call(&mut ctx, 10, 20)?; assert_eq!(result, 10); Ok(()) } @@ -170,13 +173,13 @@ fn middleware_chain_order_1(mut config: crate::Config) -> Result<()> { (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); - + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; - let result = f.call(4, 6)?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; + let result = f.call(&mut ctx, 4, 6)?; assert_eq!(result, 24); Ok(()) } @@ -194,13 +197,13 @@ fn middleware_chain_order_2(mut config: crate::Config) -> Result<()> { (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); - + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; - let result = f.call(4, 6)?; + let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; + let result = f.call(&mut ctx, 4, 6)?; assert_eq!(result, 48); Ok(()) } diff --git a/tests/compilers/native_functions.rs b/tests/compilers/native_functions.rs index bb6fba0a006..fc756576a26 100644 --- a/tests/compilers/native_functions.rs +++ b/tests/compilers/native_functions.rs @@ -2,9 +2,23 @@ use anyhow::Result; use std::convert::Infallible; use std::sync::{Arc, Mutex}; +use wasmer::Context as WasmerContext; +use wasmer::Type as ValueType; use wasmer::*; -fn long_f(a: u32, b: u32, c: u32, d: u32, e: u32, f: u16, g: u64, h: u64, i: u16, j: u32) -> u64 { +fn long_f( + _ctx: ContextMut<()>, + a: u32, + b: u32, + c: u32, + d: u32, + e: u32, + f: u16, + g: u64, + h: u64, + i: u16, + j: u32, +) -> u64 { j as u64 + i as u64 * 10 + h * 100 @@ -17,7 +31,7 @@ fn long_f(a: u32, b: u32, c: u32, d: u32, e: u32, f: u16, g: u64, h: u64, i: u16 + a as u64 * 1000000000 } -fn long_f_dynamic(values: &[Value]) -> Result, RuntimeError> { +fn long_f_dynamic(_ctx: ContextMut<()>, values: &[Value]) -> Result, RuntimeError> { Ok(vec![Value::I64( values[9].unwrap_i32() as i64 + values[8].unwrap_i32() as i64 * 10 @@ -45,58 +59,55 @@ fn native_function_works_for_wasm(config: crate::Config) -> anyhow::Result<()> { (call $multiply (local.get 1) (i32.const 2)))) )"#; let module = Module::new(&store, wat).unwrap(); + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! { "env" => { - "multiply" => Function::new_native(&store, |a: i32, b: i32| a * b), + "multiply" => Function::new_native(&mut ctx, |_ctx: ContextMut<_>, a: i32, b: i32| a * b), }, }; - - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; { - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; - let result = f.call(4, 6)?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut ctx, "add")?; + let result = f.call(&mut ctx, 4, 6)?; assert_eq!(result, 10); } { let f: &Function = instance.exports.get("double_then_add")?; - let result = f.call(&[Val::I32(4), Val::I32(6)])?; - assert_eq!(result[0], Val::I32(20)); + let result = f.call(&mut ctx, &[Value::I32(4), Value::I32(6)])?; + assert_eq!(result[0], Value::I32(20)); } { let dyn_f: &Function = instance.exports.get("double_then_add")?; - let f: TypedFunction<(i32, i32), i32> = dyn_f.native().unwrap(); - let result = f.call(4, 6)?; + let f: TypedFunction<(i32, i32), i32> = dyn_f.native(&mut ctx).unwrap(); + let result = f.call(&mut ctx, 4, 6)?; assert_eq!(result, 20); } Ok(()) } -#[should_panic( - expected = "Closures (functions with captured environments) are currently unsupported with native functions. See: https://github.com/wasmerio/wasmer/issues/1840" -)] #[compiler_test(native_functions)] fn native_host_function_closure_panics(config: crate::Config) { let store = config.store(); + let mut ctx = WasmerContext::new(&store, ()); let state = 3; - Function::new_native(&store, move |_: i32| { + Function::new_native(&mut ctx, move |_ctx: ContextMut<_>, _: i32| { println!("{}", state); }); } -#[should_panic( - expected = "Closures (functions with captured environments) are currently unsupported with native functions. See: https://github.com/wasmerio/wasmer/issues/1840" -)] #[compiler_test(native_functions)] fn native_with_env_host_function_closure_panics(config: crate::Config) { let store = config.store(); + let env: i32 = 4; + let mut ctx = WasmerContext::new(&store, env); let state = 3; - let env = 4; - Function::new_native_with_env(&store, env, move |_env: &i32, _: i32| { + Function::new_native(&mut ctx, move |_ctx: ContextMut, _: i32| { println!("{}", state); }); } @@ -122,39 +133,39 @@ fn non_native_functions_and_closures_with_no_env_work(config: crate::Config) -> (local.get 4))) )"#; let module = Module::new(&store, wat).unwrap(); - + let env: i32 = 10; + let mut ctx = WasmerContext::new(&store, env); let ty = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]); - let env = 10; let captured_by_closure = 20; let import_object = imports! { "env" => { - "multiply1" => Function::new(&store, &ty, move |args| { + "multiply1" => Function::new(&mut ctx, &ty, move |_ctx, args| { if let (Value::I32(v1), Value::I32(v2)) = (&args[0], &args[1]) { Ok(vec![Value::I32(v1 * v2 * captured_by_closure)]) } else { panic!("Invalid arguments"); } }), - "multiply2" => Function::new_with_env(&store, &ty, env, move |&env, args| { + "multiply2" => Function::new(&mut ctx, &ty, move |ctx, args| { if let (Value::I32(v1), Value::I32(v2)) = (&args[0], &args[1]) { - Ok(vec![Value::I32(v1 * v2 * captured_by_closure * env)]) + Ok(vec![Value::I32(v1 * v2 * captured_by_closure * ctx.data())]) } else { panic!("Invalid arguments"); } }), - "multiply3" => Function::new_native(&store, |arg1: i32, arg2: i32| -> i32 + "multiply3" => Function::new_native(&mut ctx, |_ctx: ContextMut<_>, arg1: i32, arg2: i32| -> i32 {arg1 * arg2 }), - "multiply4" => Function::new_native_with_env(&store, env, |&env: &i32, arg1: i32, arg2: i32| -> i32 - {arg1 * arg2 * env }), + "multiply4" => Function::new_native(&mut ctx, |ctx: ContextMut, arg1: i32, arg2: i32| -> i32 + {arg1 * arg2 * ctx.data() }), }, }; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; let test: TypedFunction<(i32, i32, i32, i32, i32), i32> = - instance.exports.get_typed_function("test")?; + instance.exports.get_typed_function(&mut ctx, "test")?; - let result = test.call(2, 3, 4, 5, 6)?; + let result = test.call(&mut ctx, 2, 3, 4, 5, 6)?; let manually_computed_result = 6 * (5 * (4 * (3 * 2 * 20) * 10 * 20)) * 10; assert_eq!(result, manually_computed_result); Ok(()) @@ -171,27 +182,27 @@ fn native_function_works_for_wasm_function_manyparams(config: crate::Config) -> (call $longf (i32.const 1) (i32.const 2) (i32.const 3) (i32.const 4) (i32.const 5) (i32.const 6) (i64.const 7) (i64.const 8) (i32.const 9) (i32.const 0))) )"#; let module = Module::new(&store, wat).unwrap(); - + let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! { "env" => { - "longf" => Function::new_native(&store, long_f), + "longf" => Function::new_native(&mut ctx, long_f), }, }; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; { let dyn_f: &Function = instance.exports.get("longf")?; - let f: TypedFunction<(), i64> = dyn_f.native().unwrap(); - let result = f.call()?; + let f: TypedFunction<(), i64> = dyn_f.native(&mut ctx).unwrap(); + let result = f.call(&mut ctx)?; assert_eq!(result, 1234567890); } { let dyn_f: &Function = instance.exports.get("longf_pure")?; let f: TypedFunction<(u32, u32, u32, u32, u32, u16, u64, u64, u16, u32), i64> = - dyn_f.native().unwrap(); - let result = f.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; + dyn_f.native(&mut ctx).unwrap(); + let result = f.call(&mut ctx, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; assert_eq!(result, 1234567890); } @@ -203,6 +214,7 @@ fn native_function_works_for_wasm_function_manyparams_dynamic( config: crate::Config, ) -> anyhow::Result<()> { let store = config.store(); + let mut ctx = WasmerContext::new(&store, ()); let wat = r#"(module (func $longf (import "env" "longf") (param i32 i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i64)) (func (export "longf_pure") (param i32 i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i64) @@ -214,24 +226,24 @@ fn native_function_works_for_wasm_function_manyparams_dynamic( let import_object = imports! { "env" => { - "longf" => Function::new(&store, FunctionType::new(vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I64 , ValType::I64 ,ValType::I32, ValType::I32], vec![ValType::I64]), long_f_dynamic), + "longf" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I64 , ValueType::I64 ,ValueType::I32, ValueType::I32], vec![ValueType::I64]), long_f_dynamic), }, }; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; { let dyn_f: &Function = instance.exports.get("longf")?; - let f: TypedFunction<(), i64> = dyn_f.native().unwrap(); - let result = f.call()?; + let f: TypedFunction<(), i64> = dyn_f.native(&mut ctx).unwrap(); + let result = f.call(&mut ctx)?; assert_eq!(result, 1234567890); } { let dyn_f: &Function = instance.exports.get("longf_pure")?; let f: TypedFunction<(u32, u32, u32, u32, u32, u16, u64, u64, u16, u32), i64> = - dyn_f.native().unwrap(); - let result = f.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; + dyn_f.native(&mut ctx).unwrap(); + let result = f.call(&mut ctx, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; assert_eq!(result, 1234567890); } @@ -241,16 +253,24 @@ fn native_function_works_for_wasm_function_manyparams_dynamic( #[compiler_test(native_functions)] fn static_host_function_without_env(config: crate::Config) -> anyhow::Result<()> { let store = config.store(); + let mut ctx = WasmerContext::new(&store, ()); - fn f(a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { + fn f(_ctx: ContextMut<()>, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { (d * 4.0, c * 3.0, b * 2, a * 1) } - fn f_ok(a: i32, b: i64, c: f32, d: f64) -> Result<(f64, f32, i64, i32), Infallible> { + fn f_ok( + _ctx: ContextMut<()>, + a: i32, + b: i64, + c: f32, + d: f64, + ) -> Result<(f64, f32, i64, i32), Infallible> { Ok((d * 4.0, c * 3.0, b * 2, a * 1)) } fn long_f( + _ctx: ContextMut<()>, a: u32, b: u32, c: u32, @@ -271,30 +291,30 @@ fn static_host_function_without_env(config: crate::Config) -> anyhow::Result<()> // Native static host function that returns a tuple. { - let f = Function::new_native(&store, f); + let f = Function::new_native(&mut ctx, f); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native().unwrap(); - let result = f_native.call(1, 3, 5.0, 7.0)?; + f.native(&mut ctx).unwrap(); + let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); } // Native static host function that returns a tuple. { - let long_f = Function::new_native(&store, long_f); + let long_f = Function::new_native(&mut ctx, long_f); let long_f_native: TypedFunction< (u32, u32, u32, u32, u32, u16, u64, u64, u16, u32), (u32, u64, u32), - > = long_f.native().unwrap(); - let result = long_f_native.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; + > = long_f.native(&mut ctx).unwrap(); + let result = long_f_native.call(&mut ctx, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; assert_eq!(result, (654321, 87, 09)); } // Native static host function that returns a result of a tuple. { - let f = Function::new_native(&store, f_ok); + let f = Function::new_native(&mut ctx, f_ok); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native().unwrap(); - let result = f_native.call(1, 3, 5.0, 7.0)?; + f.native(&mut ctx).unwrap(); + let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); } @@ -305,23 +325,29 @@ fn static_host_function_without_env(config: crate::Config) -> anyhow::Result<()> fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { let store = config.store(); - fn f(env: &Env, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { - let mut guard = env.0.lock().unwrap(); + fn f(mut ctx: ContextMut, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { + let mut guard = ctx.data_mut().0.lock().unwrap(); assert_eq!(*guard, 100); *guard = 101; (d * 4.0, c * 3.0, b * 2, a * 1) } - fn f_ok(env: &Env, a: i32, b: i64, c: f32, d: f64) -> Result<(f64, f32, i64, i32), Infallible> { - let mut guard = env.0.lock().unwrap(); + fn f_ok( + mut ctx: ContextMut, + a: i32, + b: i64, + c: f32, + d: f64, + ) -> Result<(f64, f32, i64, i32), Infallible> { + let mut guard = ctx.data_mut().0.lock().unwrap(); assert_eq!(*guard, 100); *guard = 101; Ok((d * 4.0, c * 3.0, b * 2, a * 1)) } - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env(Arc>); impl std::ops::Deref for Env { @@ -334,33 +360,35 @@ fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { // Native static host function that returns a tuple. { let env = Env(Arc::new(Mutex::new(100))); + let mut ctx = WasmerContext::new(&store, env); - let f = Function::new_native_with_env(&store, env.clone(), f); + let f = Function::new_native(&mut ctx, f); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native().unwrap(); + f.native(&mut ctx).unwrap(); - assert_eq!(*env.0.lock().unwrap(), 100); + assert_eq!(*ctx.data_mut().0.lock().unwrap(), 100); - let result = f_native.call(1, 3, 5.0, 7.0)?; + let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); - assert_eq!(*env.0.lock().unwrap(), 101); + assert_eq!(*ctx.data_mut().0.lock().unwrap(), 101); } // Native static host function that returns a result of a tuple. { let env = Env(Arc::new(Mutex::new(100))); + let mut ctx = WasmerContext::new(&store, env); - let f = Function::new_native_with_env(&store, env.clone(), f_ok); + let f = Function::new_native(&mut ctx, f_ok); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native().unwrap(); + f.native(&mut ctx).unwrap(); - assert_eq!(*env.0.lock().unwrap(), 100); + assert_eq!(*ctx.data_mut().0.lock().unwrap(), 100); - let result = f_native.call(1, 3, 5.0, 7.0)?; + let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); - assert_eq!(*env.0.lock().unwrap(), 101); + assert_eq!(*ctx.data_mut().0.lock().unwrap(), 101); } Ok(()) @@ -369,14 +397,24 @@ fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { #[compiler_test(native_functions)] fn dynamic_host_function_without_env(config: crate::Config) -> anyhow::Result<()> { let store = config.store(); - + let mut ctx = WasmerContext::new(&store, ()); let f = Function::new( - &store, + &mut ctx, FunctionType::new( - vec![ValType::I32, ValType::I64, ValType::F32, ValType::F64], - vec![ValType::F64, ValType::F32, ValType::I64, ValType::I32], + vec![ + ValueType::I32, + ValueType::I64, + ValueType::F32, + ValueType::F64, + ], + vec![ + ValueType::F64, + ValueType::F32, + ValueType::I64, + ValueType::I32, + ], ), - |values| { + |_ctx: ContextMut<_>, values| { Ok(vec![ Value::F64(values[3].unwrap_f64() * 4.0), Value::F32(values[2].unwrap_f32() * 3.0), @@ -385,8 +423,9 @@ fn dynamic_host_function_without_env(config: crate::Config) -> anyhow::Result<() ]) }, ); - let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = f.native().unwrap(); - let result = f_native.call(1, 3, 5.0, 7.0)?; + let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = + f.native(&mut ctx).unwrap(); + let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); @@ -397,7 +436,7 @@ fn dynamic_host_function_without_env(config: crate::Config) -> anyhow::Result<() fn dynamic_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { let store = config.store(); - #[derive(WasmerEnv, Clone)] + #[derive(Clone)] struct Env(Arc>); impl std::ops::Deref for Env { @@ -408,15 +447,25 @@ fn dynamic_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { } let env = Env(Arc::new(Mutex::new(100))); - let f = Function::new_with_env( - &store, + let mut ctx = WasmerContext::new(&store, env); + let f = Function::new( + &mut ctx, FunctionType::new( - vec![ValType::I32, ValType::I64, ValType::F32, ValType::F64], - vec![ValType::F64, ValType::F32, ValType::I64, ValType::I32], + vec![ + ValueType::I32, + ValueType::I64, + ValueType::F32, + ValueType::F64, + ], + vec![ + ValueType::F64, + ValueType::F32, + ValueType::I64, + ValueType::I32, + ], ), - env.clone(), - |env, values| { - let mut guard = env.0.lock().unwrap(); + |mut ctx, values| { + let mut guard = ctx.data_mut().0.lock().unwrap(); assert_eq!(*guard, 100); *guard = 101; @@ -430,14 +479,15 @@ fn dynamic_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { }, ); - let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = f.native().unwrap(); + let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = + f.native(&mut ctx).unwrap(); - assert_eq!(*env.0.lock().unwrap(), 100); + assert_eq!(*ctx.data().0.lock().unwrap(), 100); - let result = f_native.call(1, 3, 5.0, 7.0)?; + let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); - assert_eq!(*env.0.lock().unwrap(), 101); + assert_eq!(*ctx.data().0.lock().unwrap(), 101); Ok(()) } diff --git a/tests/compilers/serialize.rs b/tests/compilers/serialize.rs index 9dfbdabca3b..96306f0666a 100644 --- a/tests/compilers/serialize.rs +++ b/tests/compilers/serialize.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use wasmer::Context as WasmerContext; use wasmer::*; #[compiler_test(serialize)] @@ -53,24 +54,29 @@ fn test_deserialize(config: crate::Config) -> Result<()> { vec![Type::I32, Type::I64, Type::I32, Type::F32, Type::F64], vec![Type::I64], ); + let mut ctx = WasmerContext::new(&store, ()); + let f0 = Function::new(&mut ctx, &func_type, |_ctx, params| { + let param_0: i64 = params[0].unwrap_i32() as i64; + let param_1: i64 = params[1].unwrap_i64() as i64; + let param_2: i64 = params[2].unwrap_i32() as i64; + let param_3: i64 = params[3].unwrap_f32() as i64; + let param_4: i64 = params[4].unwrap_f64() as i64; + Ok(vec![Value::I64( + param_0 + param_1 + param_2 + param_3 + param_4, + )]) + }); let instance = Instance::new( + &mut ctx, &module, &imports! { "host" => { - "sum_part" => Function::new(&store, &func_type, |params| { - let param_0: i64 = params[0].unwrap_i32() as i64; - let param_1: i64 = params[1].unwrap_i64() as i64; - let param_2: i64 = params[2].unwrap_i32() as i64; - let param_3: i64 = params[3].unwrap_f32() as i64; - let param_4: i64 = params[4].unwrap_f64() as i64; - Ok(vec![Value::I64(param_0 + param_1 + param_2 + param_3 + param_4)]) - }) + "sum_part" => f0 } }, )?; let test_call = instance.exports.get_function("test_call")?; - let result = test_call.call(&[])?; + let result = test_call.call(&mut ctx, &[])?; assert_eq!(result.to_vec(), vec![Value::I64(1500)]); Ok(()) } diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index 77b5d6e8560..4cf7d4226fb 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -1,5 +1,6 @@ use anyhow::Result; use std::panic::{self, AssertUnwindSafe}; +use wasmer::Context as WasmerContext; use wasmer::*; #[compiler_test(traps)] @@ -13,10 +14,14 @@ fn test_trap_return(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; + let mut ctx = WasmerContext::new(&store, ()); let hello_type = FunctionType::new(vec![], vec![]); - let hello_func = Function::new(&store, &hello_type, |_| Err(RuntimeError::new("test 123"))); + let hello_func = Function::new(&mut ctx, &hello_type, |_ctx, _| { + Err(RuntimeError::new("test 123")) + }); let instance = Instance::new( + &mut ctx, &module, &imports! { "" => { @@ -29,7 +34,10 @@ fn test_trap_return(config: crate::Config) -> Result<()> { .get_function("run") .expect("expected function export"); - let e = run_func.call(&[]).err().expect("error calling function"); + let e = run_func + .call(&mut ctx, &[]) + .err() + .expect("error calling function"); assert_eq!(e.message(), "test 123"); @@ -47,14 +55,18 @@ fn test_trap_trace(config: crate::Config) -> Result<()> { ) "#; + let mut ctx = WasmerContext::new(&store, ()); let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + let instance = Instance::new(&mut ctx, &module, &imports! {})?; let run_func = instance .exports .get_function("run") .expect("expected function export"); - let e = run_func.call(&[]).err().expect("error calling function"); + let e = run_func + .call(&mut ctx, &[]) + .err() + .expect("error calling function"); let trace = e.trace(); assert_eq!(trace.len(), 2); @@ -84,11 +96,15 @@ fn test_trap_trace_cb(config: crate::Config) -> Result<()> { ) "#; + let mut ctx = WasmerContext::new(&store, ()); let fn_type = FunctionType::new(vec![], vec![]); - let fn_func = Function::new(&store, &fn_type, |_| Err(RuntimeError::new("cb throw"))); + let fn_func = Function::new(&mut ctx, &fn_type, |_ctx, _| { + Err(RuntimeError::new("cb throw")) + }); let module = Module::new(&store, wat)?; let instance = Instance::new( + &mut ctx, &module, &imports! { "" => { @@ -101,7 +117,10 @@ fn test_trap_trace_cb(config: crate::Config) -> Result<()> { .get_function("run") .expect("expected function export"); - let e = run_func.call(&[]).err().expect("error calling function"); + let e = run_func + .call(&mut ctx, &[]) + .err() + .expect("error calling function"); let trace = e.trace(); println!("Trace {:?}", trace); @@ -127,13 +146,17 @@ fn test_trap_stack_overflow(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + let mut ctx = WasmerContext::new(&store, ()); + let instance = Instance::new(&mut ctx, &module, &imports! {})?; let run_func = instance .exports .get_function("run") .expect("expected function export"); - let e = run_func.call(&[]).err().expect("error calling function"); + let e = run_func + .call(&mut ctx, &[]) + .err() + .expect("error calling function"); // We specifically don't check the stack trace here: stack traces after // stack overflows are not generally possible due to unreliable unwinding @@ -157,13 +180,17 @@ fn trap_display_pretty(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + let mut ctx = WasmerContext::new(&store, ()); + let instance = Instance::new(&mut ctx, &module, &imports! {})?; let run_func = instance .exports .get_function("bar") .expect("expected function export"); - let e = run_func.call(&[]).err().expect("error calling function"); + let e = run_func + .call(&mut ctx, &[]) + .err() + .expect("error calling function"); assert_eq!( e.to_string(), "\ @@ -190,7 +217,8 @@ fn trap_display_multi_module(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &imports! {})?; + let mut ctx = WasmerContext::new(&store, ()); + let instance = Instance::new(&mut ctx, &module, &imports! {})?; let bar = instance.exports.get_function("bar")?.clone(); let wat = r#" @@ -202,6 +230,7 @@ fn trap_display_multi_module(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; let instance = Instance::new( + &mut ctx, &module, &imports! { "" => { @@ -214,7 +243,10 @@ fn trap_display_multi_module(config: crate::Config) -> Result<()> { .get_function("bar2") .expect("expected function export"); - let e = bar2.call(&[]).err().expect("error calling function"); + let e = bar2 + .call(&mut ctx, &[]) + .err() + .expect("error calling function"); assert_eq!( e.to_string(), "\ @@ -240,9 +272,13 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; + let mut ctx = WasmerContext::new(&store, ()); let sig = FunctionType::new(vec![], vec![]); - let func = Function::new(&store, &sig, |_| Err(RuntimeError::new("user trap"))); + let func = Function::new(&mut ctx, &sig, |_ctx, _| { + Err(RuntimeError::new("user trap")) + }); let err = Instance::new( + &mut ctx, &module, &imports! { "" => { @@ -254,7 +290,7 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> { .unwrap(); match err { InstantiationError::Link(_) - | InstantiationError::HostEnvInitialization(_) + | InstantiationError::BadContext | InstantiationError::CpuFeature(_) => { panic!("It should be a start error") } @@ -279,20 +315,25 @@ fn rust_panic_import(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; + let mut ctx = WasmerContext::new(&store, ()); let sig = FunctionType::new(vec![], vec![]); - let func = Function::new(&store, &sig, |_| panic!("this is a panic")); + let func = Function::new(&mut ctx, &sig, |_ctx, _| panic!("this is a panic")); + let f0 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + panic!("this is another panic") + }); let instance = Instance::new( + &mut ctx, &module, &imports! { "" => { "foo" => func, - "bar" => Function::new_native(&store, || panic!("this is another panic")) + "bar" => f0 } }, )?; let func = instance.exports.get_function("foo")?.clone(); let err = panic::catch_unwind(AssertUnwindSafe(|| { - drop(func.call(&[])); + drop(func.call(&mut ctx, &[])); })) .unwrap_err(); assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic")); @@ -322,10 +363,12 @@ fn rust_panic_start_function(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; + let mut ctx = WasmerContext::new(&store, ()); let sig = FunctionType::new(vec![], vec![]); - let func = Function::new(&store, &sig, |_| panic!("this is a panic")); + let func = Function::new(&mut ctx, &sig, |_ctx, _| panic!("this is a panic")); let err = panic::catch_unwind(AssertUnwindSafe(|| { drop(Instance::new( + &mut ctx, &module, &imports! { "" => { @@ -337,9 +380,12 @@ fn rust_panic_start_function(config: crate::Config) -> Result<()> { .unwrap_err(); assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic")); - let func = Function::new_native(&store, || panic!("this is another panic")); + let func = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + panic!("this is another panic") + }); let err = panic::catch_unwind(AssertUnwindSafe(|| { drop(Instance::new( + &mut ctx, &module, &imports! { "" => { @@ -366,18 +412,21 @@ fn mismatched_arguments(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; - let instance = Instance::new(&module, &imports! {})?; + let mut ctx = WasmerContext::new(&store, ()); + let instance = Instance::new(&mut ctx, &module, &imports! {})?; let func: &Function = instance.exports.get("foo")?; assert_eq!( - func.call(&[]).unwrap_err().message(), + func.call(&mut ctx, &[]).unwrap_err().message(), "Parameters of type [] did not match signature [I32] -> []" ); assert_eq!( - func.call(&[Val::F32(0.0)]).unwrap_err().message(), + func.call(&mut ctx, &[Value::F32(0.0)]) + .unwrap_err() + .message(), "Parameters of type [F32] did not match signature [I32] -> []", ); assert_eq!( - func.call(&[Val::I32(0), Val::I32(1)]) + func.call(&mut ctx, &[Value::I32(0), Value::I32(1)]) .unwrap_err() .message(), "Parameters of type [I32, I32] did not match signature [I32] -> []" @@ -403,7 +452,8 @@ fn call_signature_mismatch(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; - let err = Instance::new(&module, &imports! {}) + let mut ctx = WasmerContext::new(&store, ()); + let err = Instance::new(&mut ctx, &module, &imports! {}) .err() .expect("expected error"); assert_eq!( @@ -431,7 +481,8 @@ fn start_trap_pretty(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let err = Instance::new(&module, &imports! {}) + let mut ctx = WasmerContext::new(&store, ()); + let err = Instance::new(&mut ctx, &module, &imports! {}) .err() .expect("expected error"); @@ -452,15 +503,16 @@ RuntimeError: unreachable fn present_after_module_drop(config: crate::Config) -> Result<()> { let store = config.store(); let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?; - let instance = Instance::new(&module, &imports! {})?; + let mut ctx = WasmerContext::new(&store, ()); + let instance = Instance::new(&mut ctx, &module, &imports! {})?; let func: Function = instance.exports.get_function("foo")?.clone(); println!("asserting before we drop modules"); - assert_trap(func.call(&[]).unwrap_err()); + assert_trap(func.call(&mut ctx, &[]).unwrap_err()); drop((instance, module)); println!("asserting after drop"); - assert_trap(func.call(&[]).unwrap_err()); + assert_trap(func.call(&mut ctx, &[]).unwrap_err()); return Ok(()); fn assert_trap(t: RuntimeError) { From d12759f150ae6e2047d656ec15ef2ddaff87d745 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Thu, 30 Jun 2022 15:37:39 +0200 Subject: [PATCH 15/24] Migrated internal samples to new Context API --- lib/api/src/lib.rs | 21 ++++--- lib/api/src/sys/exports.rs | 8 ++- lib/api/src/sys/externals/function.rs | 80 +++++++++++++++++---------- lib/api/src/sys/externals/global.rs | 54 +++++++++++------- lib/api/src/sys/externals/memory.rs | 30 ++++++---- lib/api/src/sys/imports.rs | 26 +++++---- lib/api/src/sys/instance.rs | 6 +- lib/api/src/sys/ptr.rs | 10 ++-- lib/api/tests/sys_reference_types.rs | 2 +- lib/middlewares/src/metering.rs | 12 ++-- lib/types/src/lib.rs | 1 - lib/types/src/types.rs | 2 +- 12 files changed, 156 insertions(+), 96 deletions(-) diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index 9bf0520290f..dcdd56e3fe2 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -41,6 +41,7 @@ //! //! ```rust //! use wasmer::{Store, Module, Instance, Value, imports}; +//! use wasmer::Context as WasmerContext; //! //! fn main() -> anyhow::Result<()> { //! let module_wat = r#" @@ -53,13 +54,14 @@ //! "#; //! //! let store = Store::default(); +//! let mut ctx = WasmerContext::new(&store, ()); //! let module = Module::new(&store, &module_wat)?; //! // The module doesn't import anything, so we create an empty import object. //! let import_object = imports! {}; -//! let instance = Instance::new(&module, &import_object)?; +//! let instance = Instance::new(&mut ctx, &module, &import_object)?; //! //! let add_one = instance.exports.get_function("add_one")?; -//! let result = add_one.call(&[Value::I32(42)])?; +//! let result = add_one.call(&mut ctx, &[Value::I32(42)])?; //! assert_eq!(result[0], Value::I32(43)); //! //! Ok(()) @@ -150,11 +152,12 @@ //! //! ``` //! # use wasmer::{imports, Function, Memory, MemoryType, Store, Imports}; -//! # fn imports_example(store: &Store) -> Imports { -//! let memory = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); +//! # use wasmer::ContextMut; +//! # fn imports_example(mut ctx: ContextMut<()>, store: &Store) -> Imports { +//! let memory = Memory::new(&mut ctx, MemoryType::new(1, None, false)).unwrap(); //! imports! { //! "env" => { -//! "my_function" => Function::new_native(store, || println!("Hello")), +//! "my_function" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>| println!("Hello")), //! "memory" => memory, //! } //! } @@ -165,12 +168,12 @@ //! from any instance via `instance.exports`: //! //! ``` -//! # use wasmer::{imports, Instance, Function, Memory, TypedFunction}; -//! # fn exports_example(instance: &Instance) -> anyhow::Result<()> { +//! # use wasmer::{imports, Instance, Function, Memory, TypedFunction, ContextMut}; +//! # fn exports_example(mut ctx: ContextMut<()>, instance: &Instance) -> anyhow::Result<()> { //! let memory = instance.exports.get_memory("memory")?; //! let memory: &Memory = instance.exports.get("some_other_memory")?; -//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("add")?; -//! let result = add.call(5, 37)?; +//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; +//! let result = add.call(&mut ctx, 5, 37)?; //! assert_eq!(result, 42); //! # Ok(()) //! # } diff --git a/lib/api/src/sys/exports.rs b/lib/api/src/sys/exports.rs index dd595d540f6..f9a66d94a19 100644 --- a/lib/api/src/sys/exports.rs +++ b/lib/api/src/sys/exports.rs @@ -18,14 +18,16 @@ use thiserror::Error; /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError}; +/// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); +/// # let mut ctx = WasmerContext::new(&store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (global $one (export "glob") f32 (f32.const 1))) /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; -/// # let instance = Instance::new(&module, &import_object).unwrap(); +/// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); /// # /// // This results with an error: `ExportError::IncompatibleType`. /// let export = instance.exports.get_function("glob").unwrap(); @@ -35,11 +37,13 @@ use thiserror::Error; /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError}; +/// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); +/// # let mut ctx = WasmerContext::new(&store, ()); /// # let wasm_bytes = wat2wasm("(module)".as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; -/// # let instance = Instance::new(&module, &import_object).unwrap(); +/// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); /// # /// // This results with an error: `ExportError::Missing`. /// let export = instance.exports.get_function("unknown").unwrap(); diff --git a/lib/api/src/sys/externals/function.rs b/lib/api/src/sys/externals/function.rs index 9d6e2d64481..d6c6cf8a8c1 100644 --- a/lib/api/src/sys/externals/function.rs +++ b/lib/api/src/sys/externals/function.rs @@ -51,11 +51,13 @@ impl Function { /// /// ``` /// # use wasmer::{Function, FunctionType, Type, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # /// let signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]); /// - /// let f = Function::new(&store, &signature, |args| { + /// let f = Function::new(&mut ctx, &signature, |_ctx, args| { /// let sum = args[0].unwrap_i32() + args[1].unwrap_i32(); /// Ok(vec![Value::I32(sum)]) /// }); @@ -65,11 +67,13 @@ impl Function { /// /// ``` /// # use wasmer::{Function, FunctionType, Type, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # /// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]); /// - /// let f = Function::new(&store, I32_I32_TO_I32, |args| { + /// let f = Function::new(&mut ctx, I32_I32_TO_I32, |_ctx, args| { /// let sum = args[0].unwrap_i32() + args[1].unwrap_i32(); /// Ok(vec![Value::I32(sum)]) /// }); @@ -152,14 +156,16 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{Store, Function}; + /// # use wasmer::{ContextMut, Store, Function}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// fn sum(a: i32, b: i32) -> i32 { + /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&store, sum); + /// let f = Function::new_native(&mut ctx, sum); /// ``` pub fn new_native(ctx: &mut impl AsContextMut, func: F) -> Self where @@ -203,17 +209,19 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{Function, Store, Type}; + /// # use wasmer::{ContextMut, Function, Store, Type}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// fn sum(a: i32, b: i32) -> i32 { + /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&store, sum); + /// let f = Function::new_native(&mut ctx, sum); /// - /// assert_eq!(f.ty().params(), vec![Type::I32, Type::I32]); - /// assert_eq!(f.ty().results(), vec![Type::I32]); + /// assert_eq!(f.ty(&mut ctx).params(), vec![Type::I32, Type::I32]); + /// assert_eq!(f.ty(&mut ctx).results(), vec![Type::I32]); /// ``` pub fn ty(&self, ctx: &impl AsContextRef) -> FunctionType { self.handle @@ -302,16 +310,18 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{Function, Store, Type}; + /// # use wasmer::{ContextMut, Function, Store, Type}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// fn sum(a: i32, b: i32) -> i32 { + /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&store, sum); + /// let f = Function::new_native(&mut ctx, sum); /// - /// assert_eq!(f.param_arity(), 2); + /// assert_eq!(f.param_arity(&mut ctx), 2); /// ``` pub fn param_arity(&self, ctx: &impl AsContextRef) -> usize { self.ty(ctx).params().len() @@ -322,16 +332,18 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{Function, Store, Type}; + /// # use wasmer::{ContextMut, Function, Store, Type}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// fn sum(a: i32, b: i32) -> i32 { + /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&store, sum); + /// let f = Function::new_native(&mut ctx, sum); /// - /// assert_eq!(f.result_arity(), 1); + /// assert_eq!(f.result_arity(&mut ctx), 1); /// ``` pub fn result_arity(&self, ctx: &impl AsContextRef) -> usize { self.ty(ctx).results().len() @@ -349,7 +361,9 @@ impl Function { /// /// ``` /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -360,11 +374,11 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); /// - /// assert_eq!(sum.call(&[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); + /// assert_eq!(sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); /// ``` pub fn call( &self, @@ -418,8 +432,10 @@ impl Function { /// # Examples /// /// ``` - /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; + /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -430,12 +446,12 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); - /// let sum_native = sum.native::<(i32, i32), i32>().unwrap(); + /// let sum_native: TypedFunction<(i32, i32), i32> = sum.native(&mut ctx).unwrap(); /// - /// assert_eq!(sum_native.call(1, 2).unwrap(), 3); + /// assert_eq!(sum_native.call(&mut ctx, 1, 2).unwrap(), 3); /// ``` /// /// # Errors @@ -444,8 +460,10 @@ impl Function { /// an error will be raised: /// /// ```should_panic - /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; + /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -456,20 +474,22 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); /// /// // This results in an error: `RuntimeError` - /// let sum_native = sum.native::<(i64, i64), i32>().unwrap(); + /// let sum_native : TypedFunction<(i64, i64), i32> = sum.native(&mut ctx).unwrap(); /// ``` /// /// If the `Rets` generic parameter does not match the exported function /// an error will be raised: /// /// ```should_panic - /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; + /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -480,12 +500,12 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); /// /// // This results in an error: `RuntimeError` - /// let sum_native = sum.native::<(i32, i32), i64>().unwrap(); + /// let sum_native: TypedFunction<(i32, i32), i64> = sum.native(&mut ctx).unwrap(); /// ``` pub fn native( &self, diff --git a/lib/api/src/sys/externals/global.rs b/lib/api/src/sys/externals/global.rs index 9e5c6c04cde..5e4f2418403 100644 --- a/lib/api/src/sys/externals/global.rs +++ b/lib/api/src/sys/externals/global.rs @@ -25,12 +25,14 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let g = Global::new(&store, Value::I32(1)); + /// let g = Global::new(&mut ctx, Value::I32(1)); /// - /// assert_eq!(g.get(), Value::I32(1)); - /// assert_eq!(g.ty().mutability, Mutability::Const); + /// assert_eq!(g.get(&mut ctx), Value::I32(1)); + /// assert_eq!(g.ty(&mut ctx).mutability, Mutability::Const); /// ``` pub fn new(ctx: &mut impl AsContextMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Const).unwrap() @@ -42,12 +44,14 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let g = Global::new_mut(&store, Value::I32(1)); + /// let g = Global::new_mut(&mut ctx, Value::I32(1)); /// - /// assert_eq!(g.get(), Value::I32(1)); - /// assert_eq!(g.ty().mutability, Mutability::Var); + /// assert_eq!(g.get(&mut ctx), Value::I32(1)); + /// assert_eq!(g.ty(&mut ctx).mutability, Mutability::Var); /// ``` pub fn new_mut(ctx: &mut impl AsContextMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Var).unwrap() @@ -83,13 +87,15 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Type, Value, GlobalType}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let c = Global::new(&store, Value::I32(1)); - /// let v = Global::new_mut(&store, Value::I64(1)); + /// let c = Global::new(&mut ctx, Value::I32(1)); + /// let v = Global::new_mut(&mut ctx, Value::I64(1)); /// - /// assert_eq!(c.ty(), &GlobalType::new(Type::I32, Mutability::Const)); - /// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var)); + /// assert_eq!(c.ty(&mut ctx), GlobalType::new(Type::I32, Mutability::Const)); + /// assert_eq!(v.ty(&mut ctx), GlobalType::new(Type::I64, Mutability::Var)); /// ``` pub fn ty(&self, ctx: &impl AsContextRef) -> GlobalType { *self.handle.get(ctx.as_context_ref().objects()).ty() @@ -101,11 +107,13 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let g = Global::new(&store, Value::I32(1)); + /// let g = Global::new(&mut ctx, Value::I32(1)); /// - /// assert_eq!(g.get(), Value::I32(1)); + /// assert_eq!(g.get(&mut ctx), Value::I32(1)); /// ``` pub fn get(&self, ctx: &mut impl AsContextMut) -> Value { unsafe { @@ -126,15 +134,17 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let g = Global::new_mut(&store, Value::I32(1)); + /// let g = Global::new_mut(&mut ctx, Value::I32(1)); /// - /// assert_eq!(g.get(), Value::I32(1)); + /// assert_eq!(g.get(&mut ctx), Value::I32(1)); /// - /// g.set(Value::I32(2)); + /// g.set(&mut ctx, Value::I32(2)); /// - /// assert_eq!(g.get(), Value::I32(2)); + /// assert_eq!(g.get(&mut ctx), Value::I32(2)); /// ``` /// /// # Errors @@ -143,23 +153,27 @@ impl Global { /// /// ```should_panic /// # use wasmer::{Global, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let g = Global::new(&store, Value::I32(1)); + /// let g = Global::new(&mut ctx, Value::I32(1)); /// - /// g.set(Value::I32(2)).unwrap(); + /// g.set(&mut ctx, Value::I32(2)).unwrap(); /// ``` /// /// Trying to set a value of a incompatible type will raise an error: /// /// ```should_panic /// # use wasmer::{Global, Store, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let g = Global::new(&store, Value::I32(1)); + /// let g = Global::new(&mut ctx, Value::I32(1)); /// /// // This results in an error: `RuntimeError`. - /// g.set(Value::I64(2)).unwrap(); + /// g.set(&mut ctx, Value::I64(2)).unwrap(); /// ``` pub fn set(&self, ctx: &mut impl AsContextMut, val: Value) -> Result<(), RuntimeError> { if !val.is_from_context(ctx) { diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 136732a773a..9434253defa 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -42,9 +42,11 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); + /// let m = Memory::new(&mut ctx, MemoryType::new(1, None, false)).unwrap(); /// ``` pub fn new(ctx: &mut impl AsContextMut, ty: MemoryType) -> Result { let mut ctx = ctx.as_context_mut(); @@ -63,12 +65,14 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # /// let mt = MemoryType::new(1, None, false); - /// let m = Memory::new(&store, mt).unwrap(); + /// let m = Memory::new(&mut ctx, mt).unwrap(); /// - /// assert_eq!(m.ty(), mt); + /// assert_eq!(m.ty(&mut ctx), mt); /// ``` pub fn ty(&self, ctx: &impl AsContextRef) -> MemoryType { self.handle.get(ctx.as_context_ref().objects()).ty() @@ -94,11 +98,13 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); + /// let m = Memory::new(&mut ctx, MemoryType::new(1, None, false)).unwrap(); /// - /// assert_eq!(m.size(), Pages(1)); + /// assert_eq!(m.size(&mut ctx), Pages(1)); /// ``` pub fn size(&self, ctx: &impl AsContextRef) -> Pages { self.handle.get(ctx.as_context_ref().objects()).size() @@ -111,13 +117,15 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let m = Memory::new(&store, MemoryType::new(1, Some(3), false)).unwrap(); - /// let p = m.grow(2).unwrap(); + /// let m = Memory::new(&mut ctx, MemoryType::new(1, Some(3), false)).unwrap(); + /// let p = m.grow(&mut ctx, 2).unwrap(); /// /// assert_eq!(p, Pages(1)); - /// assert_eq!(m.size(), Pages(3)); + /// assert_eq!(m.size(&mut ctx), Pages(3)); /// ``` /// /// # Errors @@ -127,12 +135,14 @@ impl Memory { /// /// ```should_panic /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES}; + /// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); + /// # let mut ctx = WasmerContext::new(&store, ()); /// # - /// let m = Memory::new(&store, MemoryType::new(1, Some(1), false)).unwrap(); + /// let m = Memory::new(&mut ctx, MemoryType::new(1, Some(1), false)).unwrap(); /// /// // This results in an error: `MemoryError::CouldNotGrow`. - /// let s = m.grow(1).unwrap(); + /// let s = m.grow(&mut ctx, 1).unwrap(); /// ``` pub fn grow( &self, diff --git a/lib/api/src/sys/imports.rs b/lib/api/src/sys/imports.rs index df5ee00c440..5c479c54b3c 100644 --- a/lib/api/src/sys/imports.rs +++ b/lib/api/src/sys/imports.rs @@ -16,19 +16,19 @@ use wasmer_types::ImportError; /// /// # Usage: /// ```no_run -/// use wasmer::{Exports, Module, Store, Instance, imports, Imports, Function}; -/// # fn foo_test(module: Module, store: Store) { +/// use wasmer::{ContextMut, Exports, Module, Instance, imports, Imports, Function}; +/// # fn foo_test(mut ctx: ContextMut<()>, module: Module) { /// -/// let host_fn = Function::new_native(&store, foo); +/// let host_fn = Function::new_native(&mut ctx, foo); /// let import_object: Imports = imports! { /// "env" => { /// "foo" => host_fn, /// }, /// }; /// -/// let instance = Instance::new(&module, &import_object).expect("Could not instantiate module."); +/// let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); /// -/// fn foo(n: i32) -> i32 { +/// fn foo(_ctx: ContextMut<()>, n: i32) -> i32 { /// n /// } /// @@ -97,13 +97,15 @@ impl Imports { /// /// # Usage /// ```no_run + /// # use wasmer::Context as WasmerContext; /// # let store = Default::default(); - /// use wasmer::{Imports, Function}; - /// fn foo(n: i32) -> i32 { + /// # let mut ctx = WasmerContext::new(&store, ()); + /// use wasmer::{ContextMut, Imports, Function}; + /// fn foo(_ctx: ContextMut<()>, n: i32) -> i32 { /// n /// } /// let mut import_object = Imports::new(); - /// import_object.define("env", "foo", Function::new_native(&store, foo)); + /// import_object.define("env", "foo", Function::new_native(&mut ctx, foo)); /// ``` pub fn define(&mut self, ns: &str, name: &str, val: impl Into) { self.map @@ -208,17 +210,19 @@ impl fmt::Debug for Imports { /// # Usage /// /// ``` -/// # use wasmer::{Function, Store}; +/// # use wasmer::{ContextMut, Function, Store}; +/// # use wasmer::Context as WasmerContext; /// # let store = Store::default(); +/// # let mut ctx = WasmerContext::new(&store, ()); /// use wasmer::imports; /// /// let import_object = imports! { /// "env" => { -/// "foo" => Function::new_native(&store, foo) +/// "foo" => Function::new_native(&mut ctx, foo) /// }, /// }; /// -/// fn foo(n: i32) -> i32 { +/// fn foo(_ctx: ContextMut<()>, n: i32) -> i32 { /// n /// } /// ``` diff --git a/lib/api/src/sys/instance.rs b/lib/api/src/sys/instance.rs index 3a5fdb999a9..547a12d1ba3 100644 --- a/lib/api/src/sys/instance.rs +++ b/lib/api/src/sys/instance.rs @@ -87,15 +87,17 @@ impl Instance { /// /// ``` /// # use wasmer::{imports, Store, Module, Global, Value, Instance}; + /// # use wasmer::Context as WasmerContext; /// # fn main() -> anyhow::Result<()> { /// let store = Store::default(); + /// let mut ctx = WasmerContext::new(&store, ()); /// let module = Module::new(&store, "(module)")?; /// let imports = imports!{ /// "host" => { - /// "var" => Global::new(&store, Value::I32(2)) + /// "var" => Global::new(&mut ctx, Value::I32(2)) /// } /// }; - /// let instance = Instance::new(&module, &imports)?; + /// let instance = Instance::new(&mut ctx, &module, &imports)?; /// # Ok(()) /// # } /// ``` diff --git a/lib/api/src/sys/ptr.rs b/lib/api/src/sys/ptr.rs index 46a09983c28..1f46dc84b9b 100644 --- a/lib/api/src/sys/ptr.rs +++ b/lib/api/src/sys/ptr.rs @@ -23,8 +23,9 @@ pub type WasmPtr64 = WasmPtr; /// ``` /// # use wasmer::Memory; /// # use wasmer::WasmPtr; -/// pub fn host_import(memory: Memory, ptr: WasmPtr) { -/// let derefed_ptr = ptr.deref(&memory); +/// # use wasmer::ContextMut; +/// pub fn host_import(mut ctx: ContextMut<()>, memory: Memory, ptr: WasmPtr) { +/// let derefed_ptr = ptr.deref(&mut ctx, &memory); /// let inner_val: u32 = derefed_ptr.read().expect("pointer in bounds"); /// println!("Got {} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); /// // update the value being pointed to @@ -38,6 +39,7 @@ pub type WasmPtr64 = WasmPtr; /// # use wasmer::Memory; /// # use wasmer::WasmPtr; /// # use wasmer::ValueType; +/// # use wasmer::ContextMut; /// /// // This is safe as the 12 bytes represented by this struct /// // are valid for all bit combinations. @@ -49,8 +51,8 @@ pub type WasmPtr64 = WasmPtr; /// z: f32 /// } /// -/// fn update_vector_3(memory: Memory, ptr: WasmPtr) { -/// let derefed_ptr = ptr.deref(&memory); +/// fn update_vector_3(mut ctx: ContextMut<()>, memory: Memory, ptr: WasmPtr) { +/// let derefed_ptr = ptr.deref(&mut ctx, &memory); /// let mut inner_val: V3 = derefed_ptr.read().expect("pointer in bounds"); /// println!("Got {:?} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); /// // update the value being pointed to diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs index c6024d3377d..c28ab852e47 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/sys_reference_types.rs @@ -108,7 +108,7 @@ mod sys { let instance = Instance::new(&mut ctx, &module, &imports)?; { - fn sum(ctx: ContextMut<()>, a: i32, b: i32) -> i32 { + fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { a + b } let sum_func = Function::new_native(&mut ctx, sum); diff --git a/lib/middlewares/src/metering.rs b/lib/middlewares/src/metering.rs index 49549952ba7..8c9d12a107d 100644 --- a/lib/middlewares/src/metering.rs +++ b/lib/middlewares/src/metering.rs @@ -273,12 +273,13 @@ impl u64 + Send + Sync> FunctionMiddleware for FunctionMeter /// /// ```rust /// use wasmer::Instance; +/// use wasmer::AsContextMut; /// use wasmer_middlewares::metering::{get_remaining_points, MeteringPoints}; /// /// /// Check whether the instance can continue to run based on the /// /// number of remaining points. -/// fn can_continue_to_run(instance: &Instance) -> bool { -/// matches!(get_remaining_points(instance), MeteringPoints::Remaining(points) if points > 0) +/// fn can_continue_to_run(ctx: &mut impl AsContextMut, instance: &Instance) -> bool { +/// matches!(get_remaining_points(&mut ctx.as_context_mut(), instance), MeteringPoints::Remaining(points) if points > 0) /// } /// ``` pub fn get_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance) -> MeteringPoints { @@ -320,15 +321,15 @@ pub fn get_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance) -> /// # Example /// /// ```rust -/// use wasmer::Instance; +/// use wasmer::{AsContextMut, Instance}; /// use wasmer_middlewares::metering::set_remaining_points; /// -/// fn update_remaining_points(instance: &Instance) { +/// fn update_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance) { /// // The new limit. /// let new_limit = 10; /// /// // Update the remaining points to the `new_limit`. -/// set_remaining_points(instance, new_limit); +/// set_remaining_points(&mut ctx.as_context_mut(), instance, new_limit); /// } /// ``` pub fn set_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance, points: u64) { @@ -383,6 +384,7 @@ mod tests { #[test] fn get_remaining_points_works() { + use wasmer::Context as WasmerContext; let metering = Arc::new(Metering::new(10, cost_function)); let mut compiler_config = Cranelift::default(); compiler_config.push_middleware(metering); diff --git a/lib/types/src/lib.rs b/lib/types/src/lib.rs index e04dadb6d73..d9db8b630bf 100644 --- a/lib/types/src/lib.rs +++ b/lib/types/src/lib.rs @@ -143,7 +143,6 @@ mod native { /// /// ``` /// use wasmer_types::{NativeWasmType, Type}; - /// use wasmer_types::{NativeWasmType, Type}; /// /// let wasm_type = i32::WASM_TYPE; /// assert_eq!(wasm_type, Type::I32); diff --git a/lib/types/src/types.rs b/lib/types/src/types.rs index bb27cbdb9df..bc8537055cd 100644 --- a/lib/types/src/types.rs +++ b/lib/types/src/types.rs @@ -371,7 +371,7 @@ impl GlobalType { /// Create a new Global variable /// # Usage: /// ``` - /// use wasmer_types::{GlobalType, Type, Mutability, Value}; + /// use wasmer_types::{GlobalType, Type, Mutability}; /// /// // An I32 constant global /// let global = GlobalType::new(Type::I32, Mutability::Const); From 0417111ada6110d0c16fed46ac1887e3d6b2b02f Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Fri, 24 Jun 2022 12:30:15 +0300 Subject: [PATCH 16/24] lib/c-api: update cbindgen dependency --- Cargo.lock | 68 +++++++++++++++++++++++++++++++++++++------- lib/c-api/Cargo.toml | 2 +- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ed8a3404bd..26b7f0fb2b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,7 +149,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap", + "clap 2.34.0", "env_logger", "lazy_static", "lazycell", @@ -269,12 +269,12 @@ dependencies = [ [[package]] name = "cbindgen" -version = "0.19.0" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38728c31b994e4b849cf59feefb4a8bf26acd299ee0b92c9fb35bd14ad4b8dfa" +checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" dependencies = [ - "clap", - "heck", + "clap 3.2.6", + "heck 0.4.0", "indexmap", "log", "proc-macro2", @@ -347,12 +347,36 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", - "textwrap", + "strsim 0.8.0", + "textwrap 0.11.0", "unicode-width", "vec_map", ] +[[package]] +name = "clap" +version = "3.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1fe12880bae935d142c8702d500c63a4e8634b6c3c57ad72bf978fc7b6249a" +dependencies = [ + "atty", + "bitflags", + "clap_lex", + "indexmap", + "strsim 0.10.0", + "termcolor", + "textwrap 0.15.0", +] + +[[package]] +name = "clap_lex" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87eba3c8c7f42ef17f6c659fc7416d0f4758cd3e58861ee63c5fa4a4dde649e4" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cmake" version = "0.1.48" @@ -530,7 +554,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "itertools", @@ -1070,6 +1094,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1486,6 +1516,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "output_vt100" version = "0.1.3" @@ -2237,13 +2273,19 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ - "clap", + "clap 2.34.0", "lazy_static", "structopt-derive", ] @@ -2254,7 +2296,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -2371,6 +2413,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "thiserror" version = "1.0.31" diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 00135ab4074..ff17b9cc89b 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -85,4 +85,4 @@ jit = ["universal"] #emscripten = ["wasmer-emscripten"] [build-dependencies] -cbindgen = "0.19" +cbindgen = "0.24" From 34a6511e16933435ed18cd7751cc13b1f7867f33 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Thu, 23 Jun 2022 13:51:26 +0300 Subject: [PATCH 17/24] Port C API to new Context API --- lib/api/src/sys/context.rs | 8 + lib/api/src/sys/externals/mod.rs | 5 +- lib/c-api/src/wasm_c_api/context.rs | 40 +++++ .../src/wasm_c_api/externals/function.rs | 142 ++++++------------ lib/c-api/src/wasm_c_api/externals/global.rs | 71 ++++++--- lib/c-api/src/wasm_c_api/externals/memory.rs | 62 +++++--- lib/c-api/src/wasm_c_api/externals/mod.rs | 69 ++++++++- lib/c-api/src/wasm_c_api/externals/table.rs | 17 ++- lib/c-api/src/wasm_c_api/instance.rs | 34 ++++- lib/c-api/src/wasm_c_api/mod.rs | 5 + lib/c-api/src/wasm_c_api/store.rs | 67 ++++++++- lib/c-api/src/wasm_c_api/types/function.rs | 7 +- lib/c-api/src/wasm_c_api/types/value.rs | 42 +++--- .../unstable/middlewares/metering.rs | 26 +++- lib/c-api/src/wasm_c_api/unstable/wasi.rs | 15 +- lib/c-api/src/wasm_c_api/value.rs | 34 ++--- lib/c-api/src/wasm_c_api/wasi/mod.rs | 24 +-- lib/c-api/tests/wasm-c-api/example/callback.c | 22 +-- .../tests/wasm-c-api/example/callback.cc | 32 ++-- lib/c-api/tests/wasm-c-api/example/global.cc | 44 +++--- lib/c-api/tests/wasm-c-api/example/hostref.cc | 32 ++-- lib/c-api/tests/wasm-c-api/example/memory.cc | 12 +- lib/c-api/tests/wasm-c-api/example/multi.cc | 18 +-- lib/c-api/tests/wasm-c-api/example/table.cc | 44 +++--- lib/c-api/tests/wasm-c-api/example/threads.cc | 14 +- lib/c-api/tests/wasm-c-api/example/trap.c | 10 +- lib/c-api/tests/wasm-c-api/include/wasm.h | 10 +- lib/c-api/tests/wasm-c-api/include/wasm.hh | 140 ++++++++--------- lib/c-api/tests/wasm-c-api/src/wasm-c.cc | 8 - lib/cli/src/commands/run.rs | 4 +- lib/cli/src/commands/run/wasi.rs | 4 +- 31 files changed, 648 insertions(+), 414 deletions(-) create mode 100644 lib/c-api/src/wasm_c_api/context.rs diff --git a/lib/api/src/sys/context.rs b/lib/api/src/sys/context.rs index 4289b818647..1168fe8049f 100644 --- a/lib/api/src/sys/context.rs +++ b/lib/api/src/sys/context.rs @@ -65,6 +65,14 @@ impl Context { pub fn store(&self) -> &Store { &self.inner.store } + + /// For use with the C API + /// # Safety + /// + /// This is unsafe. + pub unsafe fn transmute_data(&mut self) -> &mut Context { + core::mem::transmute::<&mut Self, &mut Context>(self) + } } /// A temporary handle to a [`Context`]. diff --git a/lib/api/src/sys/externals/mod.rs b/lib/api/src/sys/externals/mod.rs index e0e7d91235f..7625f7ca206 100644 --- a/lib/api/src/sys/externals/mod.rs +++ b/lib/api/src/sys/externals/mod.rs @@ -44,7 +44,7 @@ impl Extern { } /// Create an `Extern` from an `wasmer_engine::Export`. - pub(crate) fn from_vm_extern(ctx: &mut impl AsContextMut, vm_extern: VMExtern) -> Self { + pub fn from_vm_extern(ctx: &mut impl AsContextMut, vm_extern: VMExtern) -> Self { match vm_extern { VMExtern::Function(f) => Self::Function(Function::from_vm_extern(ctx, f)), VMExtern::Memory(m) => Self::Memory(Memory::from_vm_extern(ctx, m)), @@ -63,7 +63,8 @@ impl Extern { } } - pub(crate) fn to_vm_extern(&self) -> VMExtern { + /// To `VMExtern`. + pub fn to_vm_extern(&self) -> VMExtern { match self { Self::Function(f) => f.to_vm_extern(), Self::Global(g) => g.to_vm_extern(), diff --git a/lib/c-api/src/wasm_c_api/context.rs b/lib/c-api/src/wasm_c_api/context.rs new file mode 100644 index 00000000000..fbd6997051d --- /dev/null +++ b/lib/c-api/src/wasm_c_api/context.rs @@ -0,0 +1,40 @@ +use crate::wasm_c_api::store::wasm_store_t; +use libc::c_void; +use wasmer_api::Context; + +/// Opaque type representing a WebAssembly context. +#[allow(non_camel_case_types)] +pub struct wasm_context_t { + pub(crate) inner: Context<*mut c_void>, +} + +impl core::fmt::Debug for wasm_context_t { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "wasm_context_t") + } +} + +/// Creates a new WebAssembly Context given a specific [engine][super::engine]. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub unsafe extern "C" fn wasm_context_new( + store: Option<&wasm_store_t>, + data: *mut c_void, +) -> Option> { + let store = store?; + + Some(Box::new(wasm_context_t { + inner: Context::new(&store.inner, data), + })) +} + +/// Deletes a WebAssembly context. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub unsafe extern "C" fn wasm_context_delete(_context: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 97576e39676..f5daa91acc9 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,13 +1,15 @@ +use super::super::context::wasm_context_t; use super::super::store::wasm_store_t; use super::super::trap::wasm_trap_t; use super::super::types::{wasm_functype_t, wasm_valkind_enum}; use super::super::value::{wasm_val_inner, wasm_val_t, wasm_val_vec_t}; use super::CApiExternTag; +use std::cell::RefCell; use std::convert::TryInto; use std::ffi::c_void; use std::mem::MaybeUninit; -use std::sync::{Arc, Mutex}; -use wasmer_api::{Function, RuntimeError, Val}; +use std::rc::Rc; +use wasmer_api::{Function, RuntimeError, Value}; #[derive(Debug, Clone)] #[allow(non_camel_case_types)] @@ -15,6 +17,7 @@ use wasmer_api::{Function, RuntimeError, Val}; pub struct wasm_func_t { pub(crate) tag: CApiExternTag, pub(crate) inner: Box, + pub(crate) context: Option>>, } impl wasm_func_t { @@ -22,6 +25,7 @@ impl wasm_func_t { Self { tag: CApiExternTag::Function, inner: Box::new(function), + context: None, } } } @@ -48,91 +52,19 @@ pub unsafe extern "C" fn wasm_func_new( function_type: Option<&wasm_functype_t>, callback: Option, ) -> Option> { - let store = store?; let function_type = function_type?; let callback = callback?; - - let func_sig = &function_type.inner().function_type; - let num_rets = func_sig.results().len(); - let inner_callback = move |args: &[Val]| -> Result, RuntimeError> { - let processed_args: wasm_val_vec_t = args - .iter() - .map(TryInto::try_into) - .collect::, _>>() - .expect("Argument conversion failed") - .into(); - - let mut results: wasm_val_vec_t = vec![ - wasm_val_t { - kind: wasm_valkind_enum::WASM_I64 as _, - of: wasm_val_inner { int64_t: 0 }, - }; - num_rets - ] - .into(); - - let trap = callback(&processed_args, &mut results); - - if let Some(trap) = trap { - return Err(trap.inner); - } - - let processed_results = results - .take() - .into_iter() - .map(TryInto::try_into) - .collect::, _>>() - .expect("Result conversion failed"); - - Ok(processed_results) - }; - let function = Function::new(&store.inner, func_sig, inner_callback); - - Some(Box::new(wasm_func_t::new(function))) -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_func_new_with_env( - store: Option<&wasm_store_t>, - function_type: Option<&wasm_functype_t>, - callback: Option, - env: *mut c_void, - env_finalizer: Option, -) -> Option> { let store = store?; - let function_type = function_type?; - let callback = callback?; + if store.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let mut ctx = store.context.as_ref()?.borrow_mut(); let func_sig = &function_type.inner().function_type; let num_rets = func_sig.results().len(); - - #[derive(Clone)] - #[repr(C)] - struct WrapperEnv { - env: *mut c_void, - env_finalizer: Arc>>, - } - - impl wasmer_api::WasmerEnv for WrapperEnv {} - - // Only relevant when using multiple threads in the C API; - // Synchronization will be done via the C API / on the C side. - unsafe impl Send for WrapperEnv {} - unsafe impl Sync for WrapperEnv {} - - impl Drop for WrapperEnv { - fn drop(&mut self) { - if let Ok(mut guard) = self.env_finalizer.lock() { - if Arc::strong_count(&self.env_finalizer) == 1 { - if let Some(env_finalizer) = guard.take() { - unsafe { (env_finalizer)(self.env as _) }; - } - } - } - } - } - - let trampoline = move |env: &WrapperEnv, args: &[Val]| -> Result, RuntimeError> { + let inner_callback = move |_ctx: wasmer_api::ContextMut<'_, *mut c_void>, + args: &[Value]| + -> Result, RuntimeError> { let processed_args: wasm_val_vec_t = args .iter() .map(TryInto::try_into) @@ -149,7 +81,7 @@ pub unsafe extern "C" fn wasm_func_new_with_env( ] .into(); - let trap = callback(env.env, &processed_args, &mut results); + let trap = callback(&processed_args, &mut results); if let Some(trap) = trap { return Err(trap.inner); @@ -159,23 +91,17 @@ pub unsafe extern "C" fn wasm_func_new_with_env( .take() .into_iter() .map(TryInto::try_into) - .collect::, _>>() + .collect::, _>>() .expect("Result conversion failed"); Ok(processed_results) }; + let function = Function::new(&mut ctx.inner, func_sig, inner_callback); + drop(ctx); + let mut retval = Box::new(wasm_func_t::new(function)); + retval.context = store.context.clone(); - let function = Function::new_with_env( - &store.inner, - func_sig, - WrapperEnv { - env, - env_finalizer: Arc::new(Mutex::new(env_finalizer)), - }, - trampoline, - ); - - Some(Box::new(wasm_func_t::new(function))) + Some(retval) } #[no_mangle] @@ -194,16 +120,20 @@ pub unsafe extern "C" fn wasm_func_call( ) -> Option> { let func = func?; let args = args?; + if func.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let mut ctx = func.context.as_ref()?.borrow_mut(); let params = args .as_slice() .iter() .cloned() .map(TryInto::try_into) - .collect::, _>>() + .collect::, _>>() .expect("Arguments conversion failed"); - match func.inner.call(¶ms) { + match func.inner.call(&mut ctx.inner, ¶ms) { Ok(wasm_results) => { for (slot, val) in results .as_uninit_slice() @@ -221,17 +151,31 @@ pub unsafe extern "C" fn wasm_func_call( #[no_mangle] pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { - func.inner.ty().params().len() + let ctx = func + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + func.inner.ty(&ctx.inner).params().len() } #[no_mangle] pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { - func.inner.ty().results().len() + let ctx = func + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + func.inner.ty(&ctx.inner).results().len() } #[no_mangle] pub extern "C" fn wasm_func_type(func: Option<&wasm_func_t>) -> Option> { let func = func?; + if func.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let ctx = func.context.as_ref()?.borrow(); - Some(Box::new(wasm_functype_t::new(func.inner.ty().clone()))) + Some(Box::new(wasm_functype_t::new(func.inner.ty(&ctx.inner)))) } diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 02dd9ee49de..899a5d118d7 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -1,10 +1,13 @@ +use super::super::context::wasm_context_t; use super::super::store::wasm_store_t; use super::super::types::wasm_globaltype_t; use super::super::value::wasm_val_t; use super::CApiExternTag; use crate::error::update_last_error; +use std::cell::RefCell; use std::convert::TryInto; -use wasmer_api::{Global, Val}; +use std::rc::Rc; +use wasmer_api::{Global, Value}; #[allow(non_camel_case_types)] #[repr(C)] @@ -12,6 +15,7 @@ use wasmer_api::{Global, Val}; pub struct wasm_global_t { pub(crate) tag: CApiExternTag, pub(crate) inner: Box, + pub(crate) context: Option>>, } impl wasm_global_t { @@ -19,6 +23,7 @@ impl wasm_global_t { Self { tag: CApiExternTag::Global, inner: Box::new(global), + context: None, } } } @@ -29,20 +34,25 @@ pub unsafe extern "C" fn wasm_global_new( global_type: Option<&wasm_globaltype_t>, val: Option<&wasm_val_t>, ) -> Option> { - let store = store?; let global_type = global_type?; + let store = store?; + if store.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let mut ctx = store.context.as_ref()?.borrow_mut(); let val = val?; let global_type = &global_type.inner().global_type; let wasm_val = val.try_into().ok()?; - let store = &store.inner; let global = if global_type.mutability.is_mutable() { - Global::new_mut(store, wasm_val) + Global::new_mut(&mut ctx.inner, wasm_val) } else { - Global::new(store, wasm_val) + Global::new(&mut ctx.inner, wasm_val) }; + let mut retval = Box::new(wasm_global_t::new(global)); + retval.context = store.context.clone(); - Some(Box::new(wasm_global_t::new(global))) + Some(retval) } #[no_mangle] @@ -60,32 +70,47 @@ pub unsafe extern "C" fn wasm_global_get( // own out: &mut wasm_val_t, ) { - let value = global.inner.get(); - *out = value.try_into().unwrap(); + match global.context.as_ref() { + Some(ctx) => { + let value = global.inner.get(&mut ctx.borrow_mut().inner); + *out = value.try_into().unwrap(); + } + None => { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + } } /// Note: This function returns nothing by design but it can raise an /// error if setting a new value fails. #[no_mangle] pub unsafe extern "C" fn wasm_global_set(global: &mut wasm_global_t, val: &wasm_val_t) { - let value: Val = val.try_into().unwrap(); + match global.context.as_ref() { + Some(ctx) => { + let value: Value = val.try_into().unwrap(); - if let Err(e) = global.inner.set(value) { - update_last_error(e); + if let Err(e) = global.inner.set(&mut ctx.borrow_mut().inner, value) { + update_last_error(e); + } + } + None => { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } } } #[no_mangle] -pub unsafe extern "C" fn wasm_global_same( - wasm_global1: &wasm_global_t, - wasm_global2: &wasm_global_t, -) -> bool { - wasm_global1.inner.same(&wasm_global2.inner) -} - -#[no_mangle] -pub extern "C" fn wasm_global_type(global: &wasm_global_t) -> Box { - Box::new(wasm_globaltype_t::new(*global.inner.ty())) +pub extern "C" fn wasm_global_type( + global: Option<&wasm_global_t>, +) -> Option> { + let global = global?; + if global.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let ctx = global.context.as_ref()?.borrow(); + Some(Box::new(wasm_globaltype_t::new( + global.inner.ty(&ctx.inner), + ))) } #[cfg(test)] @@ -100,6 +125,8 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); wasm_val_t forty_two = WASM_F32_VAL(42); wasm_val_t forty_three = WASM_F32_VAL(43); @@ -132,6 +159,8 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (global $global (export \"global\") f32 (f32.const 1)))"); diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index 2e82455436f..e546f67f7a6 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -1,6 +1,9 @@ +use super::super::context::wasm_context_t; use super::super::store::wasm_store_t; use super::super::types::wasm_memorytype_t; use super::CApiExternTag; +use std::cell::RefCell; +use std::rc::Rc; use wasmer_api::{Memory, Pages}; #[allow(non_camel_case_types)] @@ -9,6 +12,7 @@ use wasmer_api::{Memory, Pages}; pub struct wasm_memory_t { pub(crate) tag: CApiExternTag, pub(crate) inner: Box, + pub(crate) context: Option>>, } impl wasm_memory_t { @@ -16,6 +20,7 @@ impl wasm_memory_t { Self { tag: CApiExternTag::Memory, inner: Box::new(memory), + context: None, } } } @@ -25,13 +30,18 @@ pub unsafe extern "C" fn wasm_memory_new( store: Option<&wasm_store_t>, memory_type: Option<&wasm_memorytype_t>, ) -> Option> { - let store = store?; let memory_type = memory_type?; + let store = store?; + if store.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let mut ctx = store.context.as_ref()?.borrow_mut(); let memory_type = memory_type.inner().memory_type; - let memory = c_try!(Memory::new(&store.inner, memory_type)); - - Some(Box::new(wasm_memory_t::new(memory))) + let memory = c_try!(Memory::new(&mut ctx.inner, memory_type)); + let mut retval = Box::new(wasm_memory_t::new(memory)); + retval.context = store.context.clone(); + Some(retval) } #[no_mangle] @@ -48,38 +58,56 @@ pub unsafe extern "C" fn wasm_memory_type( memory: Option<&wasm_memory_t>, ) -> Option> { let memory = memory?; + if memory.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let ctx = memory.context.as_ref()?.borrow(); - Some(Box::new(wasm_memorytype_t::new(memory.inner.ty()))) + Some(Box::new(wasm_memorytype_t::new( + memory.inner.ty(&ctx.inner), + ))) } // get a raw pointer into bytes #[no_mangle] pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 { - memory.inner.data_ptr() + let ctx = memory + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + memory.inner.data_ptr(&ctx.inner) } // size in bytes #[no_mangle] pub unsafe extern "C" fn wasm_memory_data_size(memory: &wasm_memory_t) -> usize { - memory.inner.size().bytes().0 + let ctx = memory + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + memory.inner.size(&ctx.inner).bytes().0 } // size in pages #[no_mangle] pub unsafe extern "C" fn wasm_memory_size(memory: &wasm_memory_t) -> u32 { - memory.inner.size().0 as _ + let ctx = memory + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + memory.inner.size(&ctx.inner).0 as _ } // delta is in pages #[no_mangle] pub unsafe extern "C" fn wasm_memory_grow(memory: &mut wasm_memory_t, delta: u32) -> bool { - memory.inner.grow(Pages(delta)).is_ok() -} - -#[no_mangle] -pub unsafe extern "C" fn wasm_memory_same( - wasm_memory1: &wasm_memory_t, - wasm_memory2: &wasm_memory_t, -) -> bool { - wasm_memory1.inner.same(&wasm_memory2.inner) + let mut ctx = memory + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow_mut(); + memory.inner.grow(&mut ctx.inner, Pages(delta)).is_ok() } diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index ebad45c9637..09d190c997f 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -3,10 +3,14 @@ mod global; mod memory; mod table; +use super::context::wasm_context_t; +use super::store::wasm_store_t; pub use function::*; pub use global::*; pub use memory::*; +use std::cell::RefCell; use std::mem::{self, ManuallyDrop}; +use std::rc::Rc; pub use table::*; use wasmer_api::{Extern, ExternType}; @@ -79,12 +83,63 @@ impl wasm_extern_t { pub(crate) fn ty(&self) -> ExternType { match self.get_tag() { - CApiExternTag::Function => { - ExternType::Function(unsafe { self.inner.function.inner.ty().clone() }) - } - CApiExternTag::Memory => ExternType::Memory(unsafe { self.inner.memory.inner.ty() }), - CApiExternTag::Global => ExternType::Global(unsafe { *self.inner.global.inner.ty() }), - CApiExternTag::Table => ExternType::Table(unsafe { *self.inner.table.inner.ty() }), + CApiExternTag::Function => unsafe { + let ctx = self + .inner + .function + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + ExternType::Function(self.inner.function.inner.ty(&ctx.inner)) + }, + CApiExternTag::Memory => unsafe { + let ctx = self + .inner + .memory + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + ExternType::Memory(self.inner.memory.inner.ty(&ctx.inner)) + }, + CApiExternTag::Global => unsafe { + let ctx = self + .inner + .global + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + ExternType::Global(self.inner.global.inner.ty(&ctx.inner)) + }, + CApiExternTag::Table => unsafe { + let ctx = self + .inner + .table + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + ExternType::Table(self.inner.table.inner.ty(&ctx.inner)) + }, + } + } + + pub(crate) fn set_context(&mut self, new_val: Option>>) { + match self.get_tag() { + CApiExternTag::Function => unsafe { + (*self.inner.function).context = new_val; + }, + CApiExternTag::Memory => unsafe { + (*self.inner.memory).context = new_val; + }, + CApiExternTag::Global => unsafe { + (*self.inner.global).context = new_val; + }, + CApiExternTag::Table => unsafe { + (*self.inner.table).context = new_val; + }, } } } @@ -265,6 +320,8 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string( diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index e5d02d6c048..c45ee56b957 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -1,6 +1,9 @@ +use super::super::context::wasm_context_t; use super::super::store::wasm_store_t; use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; use super::CApiExternTag; +use std::cell::RefCell; +use std::rc::Rc; use wasmer_api::Table; #[allow(non_camel_case_types)] @@ -9,6 +12,7 @@ use wasmer_api::Table; pub struct wasm_table_t { pub(crate) tag: CApiExternTag, pub(crate) inner: Box
, + pub(crate) context: Option>>, } impl wasm_table_t { @@ -16,6 +20,7 @@ impl wasm_table_t { Self { tag: CApiExternTag::Table, inner: Box::new(table), + context: None, } } } @@ -38,14 +43,14 @@ pub unsafe extern "C" fn wasm_table_copy(table: &wasm_table_t) -> Box bool { - table1.inner.same(&table2.inner) -} - #[no_mangle] pub unsafe extern "C" fn wasm_table_size(table: &wasm_table_t) -> usize { - table.inner.size() as _ + let ctx = table + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow(); + table.inner.size(&ctx.inner) as _ } #[no_mangle] diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 3912a092678..7e1fa6ed831 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -1,7 +1,10 @@ -use super::externals::wasm_extern_vec_t; +use super::context::wasm_context_t; +use super::externals::{wasm_extern_t, wasm_extern_vec_t}; use super::module::wasm_module_t; use super::store::wasm_store_t; use super::trap::wasm_trap_t; +use std::cell::RefCell; +use std::rc::Rc; use std::sync::Arc; use wasmer_api::{Extern, Instance, InstantiationError}; @@ -9,6 +12,7 @@ use wasmer_api::{Extern, Instance, InstantiationError}; #[allow(non_camel_case_types)] pub struct wasm_instance_t { pub(crate) inner: Arc, + pub(crate) context: Option>>, } /// Creates a new instance from a WebAssembly module and a @@ -36,11 +40,16 @@ pub struct wasm_instance_t { /// See the module's documentation. #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( - _store: Option<&wasm_store_t>, + store: Option<&wasm_store_t>, module: Option<&wasm_module_t>, imports: Option<&wasm_extern_vec_t>, trap: Option<&mut *mut wasm_trap_t>, ) -> Option> { + let store = store?; + if store.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let mut ctx = store.context.as_ref()?.borrow_mut(); let module = module?; let imports = imports?; @@ -54,7 +63,7 @@ pub unsafe extern "C" fn wasm_instance_new( .take(module_import_count) .collect::>(); - let instance = match Instance::new_by_index(wasm_module, &externs) { + let instance = match Instance::new_by_index(&mut ctx.inner, wasm_module, &externs) { Ok(instance) => Arc::new(instance), Err(InstantiationError::Link(link_error)) => { @@ -78,14 +87,17 @@ pub unsafe extern "C" fn wasm_instance_new( return None; } - Err(InstantiationError::HostEnvInitialization(error)) => { - crate::error::update_last_error(error); + Err(e @ InstantiationError::BadContext) => { + crate::error::update_last_error(e); return None; } }; - Some(Box::new(wasm_instance_t { inner: instance })) + Some(Box::new(wasm_instance_t { + inner: instance, + context: store.context.clone(), + })) } /// Deletes an instance. @@ -110,6 +122,8 @@ pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>> = instance .exports .iter() .map(|(_name, r#extern)| Some(Box::new(r#extern.clone().into()))) .collect(); + for ex in extern_vec.iter_mut().flatten() { + ex.set_context(original_instance.context.clone()); + } out.set_buffer(extern_vec); } @@ -222,6 +240,8 @@ mod tests { // Create the engine and the store. wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Create a WebAssembly module from a WAT definition. wasm_byte_vec_t wat; diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 1732669db6c..26fbd5f991b 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -21,6 +21,9 @@ //! Every module comes with examples and entry points to guide the //! discovery of this API. +/// `Context`. +mod context; + /// Private Rust macros. #[macro_use] mod macros; @@ -89,6 +92,8 @@ pub mod externals; /// // Create the engine and the store. /// wasm_engine_t* engine = wasm_engine_new(); /// wasm_store_t* store = wasm_store_new(engine); +/// wasm_context_t* ctx = wasm_context_new(store, 0); +/// wasm_store_context_set(store, ctx); /// /// // Create a WebAssembly module from a WAT definition. /// wasm_byte_vec_t wat; diff --git a/lib/c-api/src/wasm_c_api/store.rs b/lib/c-api/src/wasm_c_api/store.rs index 40d35007c10..fe5eb89de21 100644 --- a/lib/c-api/src/wasm_c_api/store.rs +++ b/lib/c-api/src/wasm_c_api/store.rs @@ -1,10 +1,20 @@ +use super::context::wasm_context_t; use super::engine::wasm_engine_t; +use libc::c_void; +use std::cell::RefCell; +use std::rc::Rc; use wasmer_api::Store; /// Opaque type representing a WebAssembly store. #[allow(non_camel_case_types)] pub struct wasm_store_t { pub(crate) inner: Store, + pub(crate) context: Option>>, +} + +impl wasm_store_t { + pub(crate) const CTX_ERR_STR: &'static str = + "store used without a Context set; use wasm_store_context_set() after initializing your store."; } /// Creates a new WebAssembly store given a specific [engine][super::engine]. @@ -19,7 +29,62 @@ pub unsafe extern "C" fn wasm_store_new( let engine = engine?; let store = Store::new_with_engine(&*engine.inner); - Some(Box::new(wasm_store_t { inner: store })) + Some(Box::new(wasm_store_t { + inner: store, + context: None, + })) +} + +/// Sets the context for this WebAssembly store. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub unsafe extern "C" fn wasm_store_context_set( + store: Option<&mut wasm_store_t>, + context: Option>, +) { + let _result = (move |store: Option<&mut wasm_store_t>, + context: Option>| + -> Option<()> { + let mut store = store?; + let context = context?; + store.context = Some(Rc::new(RefCell::new(*context))); + Some(()) + })(store, context); +} + +/// Get the value of Context data. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub unsafe extern "C" fn wasm_store_data_get(store: &wasm_store_t) -> *mut c_void { + *store + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow() + .inner + .data() +} + +/// Set the value of Context data. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub unsafe extern "C" fn wasm_store_data_set(store: &mut wasm_store_t, new_val: *mut c_void) { + *store + .context + .as_mut() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow_mut() + .inner + .data_mut() = new_val; } /// Deletes a WebAssembly store. diff --git a/lib/c-api/src/wasm_c_api/types/function.rs b/lib/c-api/src/wasm_c_api/types/function.rs index a3ff1f6bdd7..52d10d54c55 100644 --- a/lib/c-api/src/wasm_c_api/types/function.rs +++ b/lib/c-api/src/wasm_c_api/types/function.rs @@ -1,6 +1,7 @@ use super::{wasm_externtype_t, wasm_valtype_vec_t, WasmExternType}; use std::fmt; -use wasmer_api::{ExternType, FunctionType, ValType}; +use wasmer_api::{ExternType, FunctionType}; +use wasmer_types::Type; pub(crate) struct WasmFunctionType { pub(crate) function_type: FunctionType, @@ -76,12 +77,12 @@ pub unsafe extern "C" fn wasm_functype_new( let params = params?; let results = results?; - let params_as_valtype: Vec = params + let params_as_valtype: Vec = params .take() .into_iter() .map(|val| val.as_ref().unwrap().as_ref().into()) .collect::>(); - let results_as_valtype: Vec = results + let results_as_valtype: Vec = results .take() .into_iter() .map(|val| val.as_ref().unwrap().as_ref().into()) diff --git a/lib/c-api/src/wasm_c_api/types/value.rs b/lib/c-api/src/wasm_c_api/types/value.rs index 4e48dddae6e..ae2189c3117 100644 --- a/lib/c-api/src/wasm_c_api/types/value.rs +++ b/lib/c-api/src/wasm_c_api/types/value.rs @@ -1,6 +1,6 @@ use super::super::value::wasm_valkind_t; use std::convert::TryInto; -use wasmer_api::ValType; +use wasmer_api::Type; #[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -14,30 +14,30 @@ pub enum wasm_valkind_enum { WASM_FUNCREF = 129, } -impl From for wasm_valkind_enum { - fn from(other: ValType) -> Self { +impl From for wasm_valkind_enum { + fn from(other: Type) -> Self { match other { - ValType::I32 => Self::WASM_I32, - ValType::I64 => Self::WASM_I64, - ValType::F32 => Self::WASM_F32, - ValType::F64 => Self::WASM_F64, - ValType::V128 => todo!("no v128 type in Wasm C API yet!"), - ValType::ExternRef => Self::WASM_ANYREF, - ValType::FuncRef => Self::WASM_FUNCREF, + Type::I32 => Self::WASM_I32, + Type::I64 => Self::WASM_I64, + Type::F32 => Self::WASM_F32, + Type::F64 => Self::WASM_F64, + Type::V128 => todo!("no v128 type in Wasm C API yet!"), + Type::ExternRef => Self::WASM_ANYREF, + Type::FuncRef => Self::WASM_FUNCREF, } } } -impl From for ValType { +impl From for Type { fn from(other: wasm_valkind_enum) -> Self { use wasm_valkind_enum::*; match other { - WASM_I32 => ValType::I32, - WASM_I64 => ValType::I64, - WASM_F32 => ValType::F32, - WASM_F64 => ValType::F64, - WASM_ANYREF => ValType::ExternRef, - WASM_FUNCREF => ValType::FuncRef, + WASM_I32 => Type::I32, + WASM_I64 => Type::I64, + WASM_F32 => Type::F32, + WASM_F64 => Type::F64, + WASM_ANYREF => Type::ExternRef, + WASM_FUNCREF => Type::FuncRef, } } } @@ -58,20 +58,20 @@ impl Default for wasm_valtype_t { wasm_declare_boxed_vec!(valtype); -impl From for ValType { +impl From for Type { fn from(other: wasm_valtype_t) -> Self { (&other).into() } } -impl From<&wasm_valtype_t> for ValType { +impl From<&wasm_valtype_t> for Type { fn from(other: &wasm_valtype_t) -> Self { other.valkind.into() } } -impl From for wasm_valtype_t { - fn from(other: ValType) -> Self { +impl From for wasm_valtype_t { + fn from(other: Type) -> Self { Self { valkind: other.into(), } diff --git a/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs b/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs index cf64aed6aa2..bc4eb715470 100644 --- a/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs +++ b/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs @@ -45,6 +45,8 @@ //! // Create the engine and the store based on the configuration. //! wasm_engine_t* engine = wasm_engine_new_with_config(config); //! wasm_store_t* store = wasm_store_new(engine); +//! wasm_context_t* ctx = wasm_context_new(store, 0); +//! wasm_store_context_set(store, ctx); //! //! // Create the new WebAssembly module. //! wasm_byte_vec_t wat; @@ -132,6 +134,7 @@ //! ``` use super::super::super::instance::wasm_instance_t; +use super::super::super::store::wasm_store_t; use super::super::parser::operator::wasmer_parser_operator_t; use super::wasmer_middleware_t; use std::sync::Arc; @@ -202,7 +205,12 @@ pub extern "C" fn wasmer_metering_delete(_metering: Option u64 { - match get_remaining_points(&instance.inner) { + let mut ctx = instance + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow_mut(); + match get_remaining_points(&mut ctx.inner, &instance.inner) { MeteringPoints::Remaining(value) => value, MeteringPoints::Exhausted => std::u64::MAX, } @@ -215,8 +223,13 @@ pub extern "C" fn wasmer_metering_get_remaining_points(instance: &wasm_instance_ /// See module's documentation. #[no_mangle] pub extern "C" fn wasmer_metering_points_are_exhausted(instance: &wasm_instance_t) -> bool { + let mut ctx = instance + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow_mut(); matches!( - get_remaining_points(&instance.inner), + get_remaining_points(&mut ctx.inner, &instance.inner), MeteringPoints::Exhausted, ) } @@ -258,6 +271,8 @@ pub extern "C" fn wasmer_metering_points_are_exhausted(instance: &wasm_instance_ /// wasm_engine_t* engine = wasm_engine_new_with_config(config); /// /// wasm_store_t* store = wasm_store_new(engine); +/// wasm_context_t* ctx = wasm_context_new(store, 0); +/// wasm_store_context_set(store, ctx); /// /// // Create the module and instantiate it. /// wasm_byte_vec_t wat; @@ -295,7 +310,12 @@ pub extern "C" fn wasmer_metering_points_are_exhausted(instance: &wasm_instance_ /// ``` #[no_mangle] pub extern "C" fn wasmer_metering_set_remaining_points(instance: &wasm_instance_t, new_limit: u64) { - set_remaining_points(&instance.inner, new_limit); + let mut ctx = instance + .context + .as_ref() + .expect(wasm_store_t::CTX_ERR_STR) + .borrow_mut(); + set_remaining_points(&mut ctx.inner, &instance.inner, new_limit); } /// Transforms a [`wasmer_metering_t`] into a generic diff --git a/lib/c-api/src/wasm_c_api/unstable/wasi.rs b/lib/c-api/src/wasm_c_api/unstable/wasi.rs index 793db9ce079..0abbf923267 100644 --- a/lib/c-api/src/wasm_c_api/unstable/wasi.rs +++ b/lib/c-api/src/wasm_c_api/unstable/wasi.rs @@ -5,7 +5,7 @@ use super::super::{ externals::wasm_extern_t, module::wasm_module_t, store::wasm_store_t, types::wasm_name_t, wasi::wasi_env_t, }; -use wasmer_api::{Exportable, Extern}; +use wasmer_api::{AsContextMut, Extern}; use wasmer_wasi::{generate_import_object_from_ctx, get_wasi_version}; /// Unstable non-standard type wrapping `wasm_extern_t` with the @@ -162,15 +162,18 @@ fn wasi_get_unordered_imports_inner( imports: &mut wasmer_named_extern_vec_t, ) -> Option<()> { let store = store?; + if store.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let mut ctx = store.context.as_ref()?.borrow_mut(); let module = module?; - let wasi_env = wasi_env?; - - let store = &store.inner; + let _wasi_env = wasi_env?; let version = c_try!(get_wasi_version(&module.inner, false) .ok_or("could not detect a WASI version on the given module")); - let import_object = generate_import_object_from_ctx(store, wasi_env.inner.clone(), version); + let inner = unsafe { ctx.inner.transmute_data::() }; + let import_object = generate_import_object_from_ctx(&mut inner.as_context_mut(), version); imports.set_buffer( import_object @@ -178,7 +181,7 @@ fn wasi_get_unordered_imports_inner( .map(|((module, name), extern_)| { let module = module.into(); let name = name.into(); - let extern_inner = Extern::from_vm_export(store, extern_.to_vm_extern()); + let extern_inner = Extern::from_vm_extern(&mut ctx.inner, extern_.to_vm_extern()); Some(Box::new(wasmer_named_extern_t { module, diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index bb64140aa9a..db07a813b4c 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -1,7 +1,7 @@ use super::types::{wasm_ref_t, wasm_valkind_enum}; use crate::error::update_last_error; use std::convert::{TryFrom, TryInto}; -use wasmer_api::Val; +use wasmer_api::Value; /// Represents the kind of values. The variants of this C enum is /// defined in `wasm.h` to list the following: @@ -187,7 +187,7 @@ impl TryFrom for wasm_valkind_enum { } } -impl TryFrom for Val { +impl TryFrom for Value { type Error = &'static str; fn try_from(item: wasm_val_t) -> Result { @@ -195,52 +195,52 @@ impl TryFrom for Val { } } -impl TryFrom<&wasm_val_t> for Val { +impl TryFrom<&wasm_val_t> for Value { type Error = &'static str; fn try_from(item: &wasm_val_t) -> Result { Ok(match item.kind.try_into()? { - wasm_valkind_enum::WASM_I32 => Val::I32(unsafe { item.of.int32_t }), - wasm_valkind_enum::WASM_I64 => Val::I64(unsafe { item.of.int64_t }), - wasm_valkind_enum::WASM_F32 => Val::F32(unsafe { item.of.float32_t }), - wasm_valkind_enum::WASM_F64 => Val::F64(unsafe { item.of.float64_t }), + wasm_valkind_enum::WASM_I32 => Value::I32(unsafe { item.of.int32_t }), + wasm_valkind_enum::WASM_I64 => Value::I64(unsafe { item.of.int64_t }), + wasm_valkind_enum::WASM_F32 => Value::F32(unsafe { item.of.float32_t }), + wasm_valkind_enum::WASM_F64 => Value::F64(unsafe { item.of.float64_t }), wasm_valkind_enum::WASM_ANYREF => return Err("ANYREF not supported at this time"), wasm_valkind_enum::WASM_FUNCREF => return Err("FUNCREF not supported at this time"), }) } } -impl TryFrom for wasm_val_t { +impl TryFrom for wasm_val_t { type Error = &'static str; - fn try_from(item: Val) -> Result { + fn try_from(item: Value) -> Result { wasm_val_t::try_from(&item) } } -impl TryFrom<&Val> for wasm_val_t { +impl TryFrom<&Value> for wasm_val_t { type Error = &'static str; - fn try_from(item: &Val) -> Result { + fn try_from(item: &Value) -> Result { Ok(match *item { - Val::I32(v) => wasm_val_t { + Value::I32(v) => wasm_val_t { of: wasm_val_inner { int32_t: v }, kind: wasm_valkind_enum::WASM_I32 as _, }, - Val::I64(v) => wasm_val_t { + Value::I64(v) => wasm_val_t { of: wasm_val_inner { int64_t: v }, kind: wasm_valkind_enum::WASM_I64 as _, }, - Val::F32(v) => wasm_val_t { + Value::F32(v) => wasm_val_t { of: wasm_val_inner { float32_t: v }, kind: wasm_valkind_enum::WASM_F32 as _, }, - Val::F64(v) => wasm_val_t { + Value::F64(v) => wasm_val_t { of: wasm_val_inner { float64_t: v }, kind: wasm_valkind_enum::WASM_F64 as _, }, - Val::V128(_) => return Err("128bit SIMD types not yet supported in Wasm C API"), - _ => todo!("Handle these values in TryFrom for wasm_val_t"), + Value::V128(_) => return Err("128bit SIMD types not yet supported in Wasm C API"), + _ => todo!("Handle these values in TryFrom for wasm_val_t"), }) } } diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 3aa36fb48d0..1e7dc61a0b7 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -14,7 +14,7 @@ use std::convert::TryFrom; use std::ffi::CStr; use std::os::raw::c_char; use std::slice; -use wasmer_api::{Exportable, Extern}; +use wasmer_api::{AsContextMut, Extern}; use wasmer_wasi::{ generate_import_object_from_ctx, get_wasi_version, Pipe, WasiEnv, WasiFile, WasiState, WasiStateBuilder, WasiVersion, @@ -322,28 +322,28 @@ pub unsafe extern "C" fn wasi_get_wasi_version(module: &wasm_module_t) -> wasi_v pub unsafe extern "C" fn wasi_get_imports( store: Option<&wasm_store_t>, module: Option<&wasm_module_t>, - wasi_env: Option<&wasi_env_t>, imports: &mut wasm_extern_vec_t, ) -> bool { - wasi_get_imports_inner(store, module, wasi_env, imports).is_some() + wasi_get_imports_inner(store, module, imports).is_some() } fn wasi_get_imports_inner( store: Option<&wasm_store_t>, module: Option<&wasm_module_t>, - wasi_env: Option<&wasi_env_t>, imports: &mut wasm_extern_vec_t, ) -> Option<()> { let store = store?; + if store.context.is_none() { + crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); + } + let mut ctx = store.context.as_ref()?.borrow_mut(); let module = module?; - let wasi_env = wasi_env?; - - let store = &store.inner; let version = c_try!(get_wasi_version(&module.inner, false) .ok_or("could not detect a WASI version on the given module")); - let import_object = generate_import_object_from_ctx(store, wasi_env.inner.clone(), version); + let inner = unsafe { ctx.inner.transmute_data::() }; + let import_object = generate_import_object_from_ctx(&mut inner.as_context_mut(), version); imports.set_buffer(c_try!(module .inner @@ -358,7 +358,7 @@ fn wasi_get_imports_inner( import_type.name() ) })?; - let inner = Extern::from_vm_export(store, ext.to_vm_extern()); + let inner = Extern::from_vm_extern(&mut ctx.inner, ext.to_vm_extern()); Ok(Some(Box::new(inner.into()))) }) @@ -388,6 +388,7 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_unstable\" \"args_get\" (func (param i32 i32) (result i32))))"); @@ -402,6 +403,7 @@ mod tests { wasm_module_delete(module); wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); + wasm_context_delete(ctx); wasm_store_delete(store); wasm_engine_delete(engine); @@ -419,6 +421,7 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_snapshot_preview1\" \"args_get\" (func (param i32 i32) (result i32))))"); @@ -433,6 +436,7 @@ mod tests { wasm_module_delete(module); wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); + wasm_context_delete(ctx); wasm_store_delete(store); wasm_engine_delete(engine); @@ -450,6 +454,7 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_snpsht_prvw1\" \"args_get\" (func (param i32 i32) (result i32))))"); @@ -464,6 +469,7 @@ mod tests { wasm_module_delete(module); wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); + wasm_context_delete(ctx); wasm_store_delete(store); wasm_engine_delete(engine); diff --git a/lib/c-api/tests/wasm-c-api/example/callback.c b/lib/c-api/tests/wasm-c-api/example/callback.c index 2fddb1634ff..64f3d49f499 100644 --- a/lib/c-api/tests/wasm-c-api/example/callback.c +++ b/lib/c-api/tests/wasm-c-api/example/callback.c @@ -7,6 +7,8 @@ #define own +wasm_store_t* global_store = NULL; + // Print a Wasm value void wasm_val_print(wasm_val_t val) { switch (val.kind) { @@ -48,9 +50,9 @@ own wasm_trap_t* print_callback( // A function closure. own wasm_trap_t* closure_callback( - void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { - int i = *(int*)env; + int i = *(int*) wasm_store_data_get(global_store); printf("Calling back closure...\n"); printf("> %d\n", i); @@ -64,7 +66,10 @@ int main(int argc, const char* argv[]) { // Initialize. printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); - wasm_store_t* store = wasm_store_new(engine); + global_store = wasm_store_new(engine); + int i = 42; + wasm_context_t* ctx = wasm_context_new(global_store, &i); + wasm_store_context_set(global_store, ctx); // Load binary. printf("Loading binary...\n"); @@ -86,7 +91,7 @@ int main(int argc, const char* argv[]) { // Compile. printf("Compiling module...\n"); - own wasm_module_t* module = wasm_module_new(store, &binary); + own wasm_module_t* module = wasm_module_new(global_store, &binary); if (!module) { printf("> Error compiling module!\n"); return 1; @@ -97,11 +102,10 @@ int main(int argc, const char* argv[]) { // Create external print functions. printf("Creating callback...\n"); own wasm_functype_t* print_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()); - own wasm_func_t* print_func = wasm_func_new(store, print_type, print_callback); + own wasm_func_t* print_func = wasm_func_new(global_store, print_type, print_callback); - int i = 42; own wasm_functype_t* closure_type = wasm_functype_new_0_1(wasm_valtype_new_i32()); - own wasm_func_t* closure_func = wasm_func_new_with_env(store, closure_type, closure_callback, &i, NULL); + own wasm_func_t* closure_func = wasm_func_new(global_store, closure_type, closure_callback); wasm_functype_delete(print_type); wasm_functype_delete(closure_type); @@ -113,7 +117,7 @@ int main(int argc, const char* argv[]) { }; wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(store, module, &imports, NULL); + wasm_instance_new(global_store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -158,7 +162,7 @@ int main(int argc, const char* argv[]) { // Shut down. printf("Shutting down...\n"); - wasm_store_delete(store); + wasm_store_delete(global_store); wasm_engine_delete(engine); // All done. diff --git a/lib/c-api/tests/wasm-c-api/example/callback.cc b/lib/c-api/tests/wasm-c-api/example/callback.cc index 957629cabc8..27c1b6545d3 100644 --- a/lib/c-api/tests/wasm-c-api/example/callback.cc +++ b/lib/c-api/tests/wasm-c-api/example/callback.cc @@ -7,22 +7,22 @@ #include "wasm.hh" // Print a Wasm value -auto operator<<(std::ostream& out, const wasm::Val& val) -> std::ostream& { +auto operator<<(std::ostream& out, const wasm::Value& val) -> std::ostream& { switch (val.kind()) { - case wasm::ValKind::I32: { + case wasm::ValueKind::I32: { out << val.i32(); } break; - case wasm::ValKind::I64: { + case wasm::ValueKind::I64: { out << val.i64(); } break; - case wasm::ValKind::F32: { + case wasm::ValueKind::F32: { out << val.f32(); } break; - case wasm::ValKind::F64: { + case wasm::ValueKind::F64: { out << val.f64(); } break; - case wasm::ValKind::ANYREF: - case wasm::ValKind::FUNCREF: { + case wasm::ValueKind::ANYREF: + case wasm::ValueKind::FUNCREF: { if (val.ref() == nullptr) { out << "null"; } else { @@ -35,7 +35,7 @@ auto operator<<(std::ostream& out, const wasm::Val& val) -> std::ostream& { // A function to be called from Wasm code. auto print_callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl << "> " << args[0] << std::endl; results[0] = args[0].copy(); @@ -45,12 +45,12 @@ auto print_callback( // A function closure. auto closure_callback( - void* env, const wasm::vec& args, wasm::vec& results + void* env, const wasm::vec& args, wasm::vec& results ) -> wasm::own { auto i = *reinterpret_cast(env); std::cout << "Calling back closure..." << std::endl; std::cout << "> " << i << std::endl; - results[0] = wasm::Val::i32(static_cast(i)); + results[0] = wasm::Value::i32(static_cast(i)); return nullptr; } @@ -87,8 +87,8 @@ void run() { // Create external print functions. std::cout << "Creating callback..." << std::endl; auto print_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)), - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)) + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)), + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)) ); auto print_func = wasm::Func::make(store, print_type.get(), print_callback); @@ -96,8 +96,8 @@ void run() { std::cout << "Creating closure..." << std::endl; int i = 42; auto closure_type = wasm::FuncType::make( - wasm::ownvec::make(), - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)) + wasm::ownvec::make(), + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)) ); auto closure_func = wasm::Func::make(store, closure_type.get(), closure_callback, &i); @@ -122,8 +122,8 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - auto args = wasm::vec::make(wasm::Val::i32(3), wasm::Val::i32(4)); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Value::i32(3), wasm::Value::i32(4)); + auto results = wasm::vec::make_uninitialized(1); if (run_func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm-c-api/example/global.cc b/lib/c-api/tests/wasm-c-api/example/global.cc index 178eb61f8b7..a1770ef82d1 100644 --- a/lib/c-api/tests/wasm-c-api/example/global.cc +++ b/lib/c-api/tests/wasm-c-api/example/global.cc @@ -31,9 +31,9 @@ void check(T actual, U expected) { } } -auto call(const wasm::Func* func) -> wasm::Val { - auto args = wasm::vec::make(); - auto results = wasm::vec::make_uninitialized(1); +auto call(const wasm::Func* func) -> wasm::Value { + auto args = wasm::vec::make(); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -41,9 +41,9 @@ auto call(const wasm::Func* func) -> wasm::Val { return results[0].copy(); } -void call(const wasm::Func* func, wasm::Val&& arg) { - auto args = wasm::vec::make(std::move(arg)); - auto results = wasm::vec::make(); +void call(const wasm::Func* func, wasm::Value&& arg) { + auto args = wasm::vec::make(std::move(arg)); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -83,17 +83,17 @@ void run() { // Create external globals. std::cout << "Creating globals..." << std::endl; auto const_f32_type = wasm::GlobalType::make( - wasm::ValType::make(wasm::ValKind::F32), wasm::Mutability::CONST); + wasm::ValueType::make(wasm::ValueKind::F32), wasm::Mutability::CONST); auto const_i64_type = wasm::GlobalType::make( - wasm::ValType::make(wasm::ValKind::I64), wasm::Mutability::CONST); + wasm::ValueType::make(wasm::ValueKind::I64), wasm::Mutability::CONST); auto var_f32_type = wasm::GlobalType::make( - wasm::ValType::make(wasm::ValKind::F32), wasm::Mutability::VAR); + wasm::ValueType::make(wasm::ValueKind::F32), wasm::Mutability::VAR); auto var_i64_type = wasm::GlobalType::make( - wasm::ValType::make(wasm::ValKind::I64), wasm::Mutability::VAR); - auto const_f32_import = wasm::Global::make(store, const_f32_type.get(), wasm::Val::f32(1)); - auto const_i64_import = wasm::Global::make(store, const_i64_type.get(), wasm::Val::i64(2)); - auto var_f32_import = wasm::Global::make(store, var_f32_type.get(), wasm::Val::f32(3)); - auto var_i64_import = wasm::Global::make(store, var_i64_type.get(), wasm::Val::i64(4)); + wasm::ValueType::make(wasm::ValueKind::I64), wasm::Mutability::VAR); + auto const_f32_import = wasm::Global::make(store, const_f32_type.get(), wasm::Value::f32(1)); + auto const_i64_import = wasm::Global::make(store, const_i64_type.get(), wasm::Value::i64(2)); + auto var_f32_import = wasm::Global::make(store, var_f32_type.get(), wasm::Value::f32(3)); + auto var_i64_import = wasm::Global::make(store, var_i64_type.get(), wasm::Value::i64(4)); // Instantiate. std::cout << "Instantiating module..." << std::endl; @@ -154,10 +154,10 @@ void run() { check(call(get_var_i64_export).i64(), 8); // Modify variables through API and check again. - var_f32_import->set(wasm::Val::f32(33)); - var_i64_import->set(wasm::Val::i64(34)); - var_f32_export->set(wasm::Val::f32(37)); - var_i64_export->set(wasm::Val::i64(38)); + var_f32_import->set(wasm::Value::f32(33)); + var_i64_import->set(wasm::Value::i64(34)); + var_f32_export->set(wasm::Value::f32(37)); + var_i64_export->set(wasm::Value::i64(38)); check(var_f32_import->get().f32(), 33); check(var_i64_import->get().i64(), 34); @@ -170,10 +170,10 @@ void run() { check(call(get_var_i64_export).i64(), 38); // Modify variables through calls and check again. - call(set_var_f32_import, wasm::Val::f32(73)); - call(set_var_i64_import, wasm::Val::i64(74)); - call(set_var_f32_export, wasm::Val::f32(77)); - call(set_var_i64_export, wasm::Val::i64(78)); + call(set_var_f32_import, wasm::Value::f32(73)); + call(set_var_i64_import, wasm::Value::i64(74)); + call(set_var_f32_export, wasm::Value::f32(77)); + call(set_var_i64_export, wasm::Value::i64(78)); check(var_f32_import->get().f32(), 73); check(var_i64_import->get().i64(), 74); diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.cc b/lib/c-api/tests/wasm-c-api/example/hostref.cc index 09c239e0c91..f9747b91060 100644 --- a/lib/c-api/tests/wasm-c-api/example/hostref.cc +++ b/lib/c-api/tests/wasm-c-api/example/hostref.cc @@ -9,7 +9,7 @@ // A function to be called from Wasm code. auto callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> " << (args[0].ref() ? args[0].ref()->get_host_info() : nullptr) << std::endl; @@ -45,8 +45,8 @@ auto get_export_table(wasm::ownvec& exports, size_t i) -> wasm::Ta void call_r_v(const wasm::Func* func, const wasm::Ref* ref) { std::cout << "call_r_v... " << std::flush; - auto args = wasm::vec::make(wasm::Val::ref(ref ? ref->copy() : wasm::own())); - auto results = wasm::vec::make(); + auto args = wasm::vec::make(wasm::Value::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -56,8 +56,8 @@ void call_r_v(const wasm::Func* func, const wasm::Ref* ref) { auto call_v_r(const wasm::Func* func) -> wasm::own { std::cout << "call_v_r... " << std::flush; - auto args = wasm::vec::make(); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -68,8 +68,8 @@ auto call_v_r(const wasm::Func* func) -> wasm::own { auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own { std::cout << "call_r_r... " << std::flush; - auto args = wasm::vec::make(wasm::Val::ref(ref ? ref->copy() : wasm::own())); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Value::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -80,9 +80,9 @@ auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own::make( - wasm::Val::i32(i), wasm::Val::ref(ref ? ref->copy() : wasm::own())); - auto results = wasm::vec::make(); + auto args = wasm::vec::make( + wasm::Value::i32(i), wasm::Value::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -92,8 +92,8 @@ void call_ir_v(const wasm::Func* func, int32_t i, const wasm::Ref* ref) { auto call_i_r(const wasm::Func* func, int32_t i) -> wasm::own { std::cout << "call_i_r... " << std::flush; - auto args = wasm::vec::make(wasm::Val::i32(i)); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Value::i32(i)); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -144,8 +144,8 @@ void run() { // Create external callback function. std::cout << "Creating callback..." << std::endl; auto callback_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::ANYREF)), - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::ANYREF)) + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::ANYREF)), + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::ANYREF)) ); auto callback_func = wasm::Func::make(store, callback_type.get(), callback); @@ -182,7 +182,7 @@ void run() { check(host1->copy(), host1.get()); check(host2->copy(), host2.get()); - wasm::Val val = wasm::Val::ref(host1->copy()); + wasm::Value val = wasm::Value::ref(host1->copy()); check(val.ref()->copy(), host1.get()); auto ref = val.release_ref(); assert(val.ref() == nullptr); @@ -199,7 +199,7 @@ void run() { check(call_v_r(global_get), nullptr); check(global->get().release_ref(), nullptr); - global->set(wasm::Val(host2->copy())); + global->set(wasm::Value(host2->copy())); check(call_v_r(global_get), host2.get()); check(global->get().release_ref(), host2.get()); diff --git a/lib/c-api/tests/wasm-c-api/example/memory.cc b/lib/c-api/tests/wasm-c-api/example/memory.cc index 6cc36192a85..4f0bf20f3e7 100644 --- a/lib/c-api/tests/wasm-c-api/example/memory.cc +++ b/lib/c-api/tests/wasm-c-api/example/memory.cc @@ -33,8 +33,8 @@ void check(T actual, U expected) { template void check_ok(const wasm::Func* func, Args... xs) { - auto args = wasm::vec::make(wasm::Val::i32(xs)...); - auto results = wasm::vec::make(); + auto args = wasm::vec::make(wasm::Value::i32(xs)...); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); @@ -43,8 +43,8 @@ void check_ok(const wasm::Func* func, Args... xs) { template void check_trap(const wasm::Func* func, Args... xs) { - auto args = wasm::vec::make(wasm::Val::i32(xs)...); - auto results = wasm::vec::make(); + auto args = wasm::vec::make(wasm::Value::i32(xs)...); + auto results = wasm::vec::make(); if (! func->call(args, results)) { std::cout << "> Error on result, expected trap" << std::endl; exit(1); @@ -53,8 +53,8 @@ void check_trap(const wasm::Func* func, Args... xs) { template auto call(const wasm::Func* func, Args... xs) -> int32_t { - auto args = wasm::vec::make(wasm::Val::i32(xs)...); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Value::i32(xs)...); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm-c-api/example/multi.cc b/lib/c-api/tests/wasm-c-api/example/multi.cc index 6d083557114..7c167a727e1 100644 --- a/lib/c-api/tests/wasm-c-api/example/multi.cc +++ b/lib/c-api/tests/wasm-c-api/example/multi.cc @@ -8,7 +8,7 @@ // A function to be called from Wasm code. auto callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> " << args[0].i32(); @@ -54,11 +54,11 @@ void run() { // Create external print functions. std::cout << "Creating callback..." << std::endl; - auto tuple = wasm::ownvec::make( - wasm::ValType::make(wasm::ValKind::I32), - wasm::ValType::make(wasm::ValKind::I64), - wasm::ValType::make(wasm::ValKind::I64), - wasm::ValType::make(wasm::ValKind::I32) + auto tuple = wasm::ownvec::make( + wasm::ValueType::make(wasm::ValueKind::I32), + wasm::ValueType::make(wasm::ValueKind::I64), + wasm::ValueType::make(wasm::ValueKind::I64), + wasm::ValueType::make(wasm::ValueKind::I32) ); auto callback_type = wasm::FuncType::make(tuple.deep_copy(), tuple.deep_copy()); @@ -84,10 +84,10 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - auto args = wasm::vec::make( - wasm::Val::i32(1), wasm::Val::i64(2), wasm::Val::i64(3), wasm::Val::i32(4) + auto args = wasm::vec::make( + wasm::Value::i32(1), wasm::Value::i64(2), wasm::Value::i64(3), wasm::Value::i32(4) ); - auto results = wasm::vec::make_uninitialized(4); + auto results = wasm::vec::make_uninitialized(4); if (wasm::own trap = run_func->call(args, results)) { std::cout << "> Error calling function! " << trap->message().get() << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm-c-api/example/table.cc b/lib/c-api/tests/wasm-c-api/example/table.cc index 9ddf1d902bf..d937ec9038a 100644 --- a/lib/c-api/tests/wasm-c-api/example/table.cc +++ b/lib/c-api/tests/wasm-c-api/example/table.cc @@ -9,10 +9,10 @@ // A function to be called from Wasm code. auto neg_callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; - results[0] = wasm::Val(-args[0].i32()); + results[0] = wasm::Value(-args[0].i32()); return nullptr; } @@ -49,10 +49,10 @@ void check(bool success) { } auto call( - const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2 -) -> wasm::Val { - auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); - auto results = wasm::vec::make_uninitialized(1); + const wasm::Func* func, wasm::Value&& arg1, wasm::Value&& arg2 +) -> wasm::Value { + auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); @@ -60,9 +60,9 @@ auto call( return results[0].copy(); } -void check_trap(const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2) { - auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); - auto results = wasm::vec::make_uninitialized(1); +void check_trap(const wasm::Func* func, wasm::Value&& arg1, wasm::Value&& arg2) { + auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); + auto results = wasm::vec::make_uninitialized(1); if (! func->call(args, results)) { std::cout << "> Error on result, expected trap" << std::endl; exit(1); @@ -119,8 +119,8 @@ void run() { // Create external function. std::cout << "Creating callback..." << std::endl; auto neg_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)), - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)) + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)), + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)) ); auto h = wasm::Func::make(store, neg_type.get(), neg_callback); @@ -132,9 +132,9 @@ void run() { check(table->size(), 2u); check(table->get(0) == nullptr); check(table->get(1) != nullptr); - check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(0)); - check(call(call_indirect, wasm::Val::i32(7), wasm::Val::i32(1)).i32(), 7); - check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(2)); + check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(0)); + check(call(call_indirect, wasm::Value::i32(7), wasm::Value::i32(1)).i32(), 7); + check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(2)); // Mutate table. std::cout << "Mutating table..." << std::endl; @@ -143,9 +143,9 @@ void run() { check(! table->set(2, f)); check(table->get(0) != nullptr); check(table->get(1) == nullptr); - check(call(call_indirect, wasm::Val::i32(7), wasm::Val::i32(0)).i32(), 666); - check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(1)); - check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(2)); + check(call(call_indirect, wasm::Value::i32(7), wasm::Value::i32(0)).i32(), 666); + check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(1)); + check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(2)); // Grow table. std::cout << "Growing table..." << std::endl; @@ -157,10 +157,10 @@ void run() { check(table->get(2) != nullptr); check(table->get(3) != nullptr); check(table->get(4) == nullptr); - check(call(call_indirect, wasm::Val::i32(5), wasm::Val::i32(2)).i32(), 5); - check(call(call_indirect, wasm::Val::i32(6), wasm::Val::i32(3)).i32(), -6); - check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(4)); - check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(5)); + check(call(call_indirect, wasm::Value::i32(5), wasm::Value::i32(2)).i32(), 5); + check(call(call_indirect, wasm::Value::i32(6), wasm::Value::i32(3)).i32(), -6); + check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(4)); + check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(5)); check(table->grow(2, f)); check(table->size(), 7u); @@ -175,7 +175,7 @@ void run() { // TODO(wasm+): Once Wasm allows multiple tables, turn this into import. std::cout << "Creating stand-alone table..." << std::endl; auto tabletype = wasm::TableType::make( - wasm::ValType::make(wasm::ValKind::FUNCREF), wasm::Limits(5, 5)); + wasm::ValueType::make(wasm::ValueKind::FUNCREF), wasm::Limits(5, 5)); auto table2 = wasm::Table::make(store, tabletype.get()); check(table2->size() == 5); check(! table2->grow(1)); diff --git a/lib/c-api/tests/wasm-c-api/example/threads.cc b/lib/c-api/tests/wasm-c-api/example/threads.cc index e130717a0cf..cde5f3a3676 100644 --- a/lib/c-api/tests/wasm-c-api/example/threads.cc +++ b/lib/c-api/tests/wasm-c-api/example/threads.cc @@ -10,9 +10,9 @@ const int N_REPS = 3; // A function to be called from Wasm code. auto callback( - void* env, const wasm::vec& args, wasm::vec& results + void* env, const wasm::vec& args, wasm::vec& results ) -> wasm::own { - assert(args[0].kind() == wasm::ValKind::I32); + assert(args[0].kind() == wasm::ValueKind::I32); std::lock_guard lock(*reinterpret_cast(env)); std::cout << "Thread " << args[0].i32() << " running..." << std::endl; std::cout.flush(); @@ -42,15 +42,15 @@ void run( // Create imports. auto func_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)), - wasm::ownvec::make() + wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)), + wasm::ownvec::make() ); auto func = wasm::Func::make(store, func_type.get(), callback, mutex); auto global_type = wasm::GlobalType::make( - wasm::ValType::make(wasm::ValKind::I32), wasm::Mutability::CONST); + wasm::ValueType::make(wasm::ValueKind::I32), wasm::Mutability::CONST); auto global = wasm::Global::make( - store, global_type.get(), wasm::Val::i32(i)); + store, global_type.get(), wasm::Value::i32(i)); // Instantiate. auto imports = wasm::vec::make(func.get(), global.get()); @@ -71,7 +71,7 @@ void run( auto run_func = exports[0]->func(); // Call. - auto empty = wasm::vec::make(); + auto empty = wasm::vec::make(); run_func->call(empty, empty); } } diff --git a/lib/c-api/tests/wasm-c-api/example/trap.c b/lib/c-api/tests/wasm-c-api/example/trap.c index 1146f69e621..7b13d673539 100644 --- a/lib/c-api/tests/wasm-c-api/example/trap.c +++ b/lib/c-api/tests/wasm-c-api/example/trap.c @@ -7,14 +7,16 @@ #define own +wasm_store_t* store = NULL; + // A function to be called from Wasm code. own wasm_trap_t* fail_callback( - void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); own wasm_name_t message; wasm_name_new_from_string_nt(&message, "callback abort"); - own wasm_trap_t* trap = wasm_trap_new((wasm_store_t*)env, &message); + own wasm_trap_t* trap = wasm_trap_new(store, &message); wasm_name_delete(&message); return trap; } @@ -34,7 +36,7 @@ int main(int argc, const char* argv[]) { // Initialize. printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); - wasm_store_t* store = wasm_store_new(engine); + store = wasm_store_new(engine); // Load binary. printf("Loading binary...\n"); @@ -69,7 +71,7 @@ int main(int argc, const char* argv[]) { own wasm_functype_t* fail_type = wasm_functype_new_0_1(wasm_valtype_new_i32()); own wasm_func_t* fail_func = - wasm_func_new_with_env(store, fail_type, fail_callback, store, NULL); + wasm_func_new(store, fail_type, fail_callback); wasm_functype_delete(fail_type); diff --git a/lib/c-api/tests/wasm-c-api/include/wasm.h b/lib/c-api/tests/wasm-c-api/include/wasm.h index 25e0453a3ab..6540804cd67 100644 --- a/lib/c-api/tests/wasm-c-api/include/wasm.h +++ b/lib/c-api/tests/wasm-c-api/include/wasm.h @@ -143,6 +143,13 @@ WASM_DECLARE_OWN(store) WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*); +// Context + +WASM_DECLARE_OWN(context) + +WASM_API_EXTERN own void wasm_store_context_set(own wasm_store_t*, own wasm_context_t*); +WASM_API_EXTERN own void wasm_store_data_set(own wasm_store_t*, own void*); +WASM_API_EXTERN own void* wasm_store_data_get(own wasm_store_t*); /////////////////////////////////////////////////////////////////////////////// // Type Representations @@ -420,9 +427,6 @@ typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)( WASM_API_EXTERN own wasm_func_t* wasm_func_new( wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t); -WASM_API_EXTERN own wasm_func_t* wasm_func_new_with_env( - wasm_store_t*, const wasm_functype_t* type, wasm_func_callback_with_env_t, - void* env, void (*finalizer)(void*)); WASM_API_EXTERN own wasm_functype_t* wasm_func_type(const wasm_func_t*); WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*); diff --git a/lib/c-api/tests/wasm-c-api/include/wasm.hh b/lib/c-api/tests/wasm-c-api/include/wasm.hh index 597c10f4d8c..f0b3ee21a78 100644 --- a/lib/c-api/tests/wasm-c-api/include/wasm.hh +++ b/lib/c-api/tests/wasm-c-api/include/wasm.hh @@ -128,7 +128,7 @@ public: return v; } - // TODO: This can't be used for e.g. vec + // TODO: This can't be used for e.g. vec auto deep_copy() const -> vec { auto v = vec(size_); if (v) for (size_t i = 0; i < size_; ++i) v.data_[i] = data_[i]->copy(); @@ -246,25 +246,25 @@ struct Limits { // Value Types -enum class ValKind : uint8_t { +enum class ValueKind : uint8_t { I32, I64, F32, F64, ANYREF = 128, FUNCREF, }; -inline bool is_num(ValKind k) { return k < ValKind::ANYREF; } -inline bool is_ref(ValKind k) { return k >= ValKind::ANYREF; } +inline bool is_num(ValueKind k) { return k < ValueKind::ANYREF; } +inline bool is_ref(ValueKind k) { return k >= ValueKind::ANYREF; } -class WASM_API_EXTERN ValType { +class WASM_API_EXTERN ValueType { public: - ValType() = delete; - ~ValType(); + ValueType() = delete; + ~ValueType(); void operator delete(void*); - static auto make(ValKind) -> own; - auto copy() const -> own; + static auto make(ValueKind) -> own; + auto copy() const -> own; - auto kind() const -> ValKind; + auto kind() const -> ValueKind; auto is_num() const -> bool { return wasm::is_num(kind()); } auto is_ref() const -> bool { return wasm::is_ref(kind()); } }; @@ -311,14 +311,14 @@ public: ~FuncType(); static auto make( - ownvec&& params = ownvec::make(), - ownvec&& results = ownvec::make() + ownvec&& params = ownvec::make(), + ownvec&& results = ownvec::make() ) -> own; auto copy() const -> own; - auto params() const -> const ownvec&; - auto results() const -> const ownvec&; + auto params() const -> const ownvec&; + auto results() const -> const ownvec&; }; @@ -329,10 +329,10 @@ public: GlobalType() = delete; ~GlobalType(); - static auto make(own&&, Mutability) -> own; + static auto make(own&&, Mutability) -> own; auto copy() const -> own; - auto content() const -> const ValType*; + auto content() const -> const ValueType*; auto mutability() const -> Mutability; }; @@ -344,10 +344,10 @@ public: TableType() = delete; ~TableType(); - static auto make(own&&, Limits) -> own; + static auto make(own&&, Limits) -> own; auto copy() const -> own; - auto element() const -> const ValType*; + auto element() const -> const ValueType*; auto limits() const -> const Limits&; }; @@ -423,8 +423,8 @@ public: // Values -class Val { - ValKind kind_; +class Value { + ValueKind kind_; union impl { int32_t i32; int64_t i64; @@ -433,34 +433,34 @@ class Val { Ref* ref; } impl_; - Val(ValKind kind, impl impl) : kind_(kind), impl_(impl) {} + Value(ValueKind kind, impl impl) : kind_(kind), impl_(impl) {} public: - Val() : kind_(ValKind::ANYREF) { impl_.ref = nullptr; } - explicit Val(int32_t i) : kind_(ValKind::I32) { impl_.i32 = i; } - explicit Val(int64_t i) : kind_(ValKind::I64) { impl_.i64 = i; } - explicit Val(float32_t z) : kind_(ValKind::F32) { impl_.f32 = z; } - explicit Val(float64_t z) : kind_(ValKind::F64) { impl_.f64 = z; } - explicit Val(own&& r) : kind_(ValKind::ANYREF) { impl_.ref = r.release(); } - - Val(Val&& that) : kind_(that.kind_), impl_(that.impl_) { + Value() : kind_(ValueKind::ANYREF) { impl_.ref = nullptr; } + explicit Value(int32_t i) : kind_(ValueKind::I32) { impl_.i32 = i; } + explicit Value(int64_t i) : kind_(ValueKind::I64) { impl_.i64 = i; } + explicit Value(float32_t z) : kind_(ValueKind::F32) { impl_.f32 = z; } + explicit Value(float64_t z) : kind_(ValueKind::F64) { impl_.f64 = z; } + explicit Value(own&& r) : kind_(ValueKind::ANYREF) { impl_.ref = r.release(); } + + Value(Value&& that) : kind_(that.kind_), impl_(that.impl_) { if (is_ref()) that.impl_.ref = nullptr; } - ~Val() { + ~Value() { reset(); } auto is_num() const -> bool { return wasm::is_num(kind_); } auto is_ref() const -> bool { return wasm::is_ref(kind_); } - static auto i32(int32_t x) -> Val { return Val(x); } - static auto i64(int64_t x) -> Val { return Val(x); } - static auto f32(float32_t x) -> Val { return Val(x); } - static auto f64(float64_t x) -> Val { return Val(x); } - static auto ref(own&& x) -> Val { return Val(std::move(x)); } - template inline static auto make(T x) -> Val; - template inline static auto make(own&& x) -> Val; + static auto i32(int32_t x) -> Value { return Value(x); } + static auto i64(int64_t x) -> Value { return Value(x); } + static auto f32(float32_t x) -> Value { return Value(x); } + static auto f64(float64_t x) -> Value { return Value(x); } + static auto ref(own&& x) -> Value { return Value(std::move(x)); } + template inline static auto make(T x) -> Value; + template inline static auto make(own&& x) -> Value; void reset() { if (is_ref() && impl_.ref) { @@ -469,23 +469,23 @@ public: } } - void reset(Val& that) { + void reset(Value& that) { reset(); kind_ = that.kind_; impl_ = that.impl_; if (is_ref()) that.impl_.ref = nullptr; } - auto operator=(Val&& that) -> Val& { + auto operator=(Value&& that) -> Value& { reset(that); return *this; } - auto kind() const -> ValKind { return kind_; } - auto i32() const -> int32_t { assert(kind_ == ValKind::I32); return impl_.i32; } - auto i64() const -> int64_t { assert(kind_ == ValKind::I64); return impl_.i64; } - auto f32() const -> float32_t { assert(kind_ == ValKind::F32); return impl_.f32; } - auto f64() const -> float64_t { assert(kind_ == ValKind::F64); return impl_.f64; } + auto kind() const -> ValueKind { return kind_; } + auto i32() const -> int32_t { assert(kind_ == ValueKind::I32); return impl_.i32; } + auto i64() const -> int64_t { assert(kind_ == ValueKind::I64); return impl_.i64; } + auto f32() const -> float32_t { assert(kind_ == ValueKind::F32); return impl_.f32; } + auto f64() const -> float64_t { assert(kind_ == ValueKind::F64); return impl_.f64; } auto ref() const -> Ref* { assert(is_ref()); return impl_.ref; } template inline auto get() const -> T; @@ -496,45 +496,45 @@ public: return own(ref); } - auto copy() const -> Val { + auto copy() const -> Value { if (is_ref() && impl_.ref != nullptr) { // TODO(mvsc): MVSC cannot handle this: // impl impl = {.ref = impl_.ref->copy().release()}; impl impl; impl.ref = impl_.ref->copy().release(); - return Val(kind_, impl); + return Value(kind_, impl); } else { - return Val(kind_, impl_); + return Value(kind_, impl_); } } }; -template<> inline auto Val::make(int32_t x) -> Val { return Val(x); } -template<> inline auto Val::make(int64_t x) -> Val { return Val(x); } -template<> inline auto Val::make(float32_t x) -> Val { return Val(x); } -template<> inline auto Val::make(float64_t x) -> Val { return Val(x); } -template<> inline auto Val::make(own&& x) -> Val { - return Val(std::move(x)); +template<> inline auto Value::make(int32_t x) -> Value { return Value(x); } +template<> inline auto Value::make(int64_t x) -> Value { return Value(x); } +template<> inline auto Value::make(float32_t x) -> Value { return Value(x); } +template<> inline auto Value::make(float64_t x) -> Value { return Value(x); } +template<> inline auto Value::make(own&& x) -> Value { + return Value(std::move(x)); } -template<> inline auto Val::make(uint32_t x) -> Val { - return Val(static_cast(x)); +template<> inline auto Value::make(uint32_t x) -> Value { + return Value(static_cast(x)); } -template<> inline auto Val::make(uint64_t x) -> Val { - return Val(static_cast(x)); +template<> inline auto Value::make(uint64_t x) -> Value { + return Value(static_cast(x)); } -template<> inline auto Val::get() const -> int32_t { return i32(); } -template<> inline auto Val::get() const -> int64_t { return i64(); } -template<> inline auto Val::get() const -> float32_t { return f32(); } -template<> inline auto Val::get() const -> float64_t { return f64(); } -template<> inline auto Val::get() const -> Ref* { return ref(); } +template<> inline auto Value::get() const -> int32_t { return i32(); } +template<> inline auto Value::get() const -> int64_t { return i64(); } +template<> inline auto Value::get() const -> float32_t { return f32(); } +template<> inline auto Value::get() const -> float64_t { return f64(); } +template<> inline auto Value::get() const -> Ref* { return ref(); } -template<> inline auto Val::get() const -> uint32_t { +template<> inline auto Value::get() const -> uint32_t { return static_cast(i32()); } -template<> inline auto Val::get() const -> uint64_t { +template<> inline auto Value::get() const -> uint64_t { return static_cast(i64()); } @@ -654,8 +654,8 @@ public: Func() = delete; ~Func(); - using callback = auto (*)(const vec&, vec&) -> own; - using callback_with_env = auto (*)(void*, const vec&, vec&) -> own; + using callback = auto (*)(const vec&, vec&) -> own; + using callback_with_env = auto (*)(void*, const vec&, vec&) -> own; static auto make(Store*, const FuncType*, callback) -> own; static auto make(Store*, const FuncType*, callback_with_env, @@ -666,7 +666,7 @@ public: auto param_arity() const -> size_t; auto result_arity() const -> size_t; - auto call(const vec&, vec&) const -> own; + auto call(const vec&, vec&) const -> own; }; @@ -677,12 +677,12 @@ public: Global() = delete; ~Global(); - static auto make(Store*, const GlobalType*, const Val&) -> own; + static auto make(Store*, const GlobalType*, const Value&) -> own; auto copy() const -> own; auto type() const -> own; - auto get() const -> Val; - void set(const Val&); + auto get() const -> Value; + void set(const Value&); }; diff --git a/lib/c-api/tests/wasm-c-api/src/wasm-c.cc b/lib/c-api/tests/wasm-c-api/src/wasm-c.cc index b4316116148..23f8151c77b 100644 --- a/lib/c-api/tests/wasm-c-api/src/wasm-c.cc +++ b/lib/c-api/tests/wasm-c-api/src/wasm-c.cc @@ -815,14 +815,6 @@ wasm_func_t* wasm_func_new( store, type, wasm_callback, reinterpret_cast(callback))); } -wasm_func_t *wasm_func_new_with_env( - wasm_store_t* store, const wasm_functype_t* type, - wasm_func_callback_with_env_t callback, void *env, void (*finalizer)(void*) -) { - auto env2 = new wasm_callback_env_t{callback, env, finalizer}; - return release_func(Func::make(store, type, wasm_callback_with_env, env2, wasm_callback_env_finalizer)); -} - wasm_functype_t* wasm_func_type(const wasm_func_t* func) { return release_functype(func->type()); } diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index b5ee6e6f0b4..128fd1c7a10 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -111,7 +111,7 @@ impl Run { let imports = imports! {}; let instance = Instance::new(&mut ctx, &module, &imports)?; let result = - self.invoke_function(&mut ctx.as_context_mut(), &instance, &invoke, &self.args)?; + self.invoke_function(&mut ctx.as_context_mut(), &instance, invoke, &self.args)?; println!( "{}", result @@ -380,7 +380,7 @@ impl Run { invoke: &str, args: &[String], ) -> Result> { - let func: Function = self.try_find_function(&instance, invoke, args)?; + let func: Function = self.try_find_function(instance, invoke, args)?; let func_ty = func.ty(ctx); let required_arguments = func_ty.params().len(); let provided_arguments = args.len(); diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index 60be4660e33..5cf8287edde 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -104,9 +104,9 @@ impl Wasi { is_wasix_module(module), std::sync::atomic::Ordering::Release, ); - let mut ctx = Context::new(module.store(), wasi_env.clone()); + let mut ctx = Context::new(module.store(), wasi_env); let import_object = import_object_for_all_wasi_versions(&mut ctx.as_context_mut()); - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut ctx, module, &import_object)?; let memory = instance.exports.get_memory("memory")?; ctx.data_mut().set_memory(memory.clone()); Ok((ctx, instance)) From a67e17db6af7eb36ecd1da4e78869a8e39e01967 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 28 Jun 2022 15:12:03 +0300 Subject: [PATCH 18/24] lib/compiler: delete left-over file --- lib/compiler/src/engine/export.rs | 166 ------------------------------ 1 file changed, 166 deletions(-) delete mode 100644 lib/compiler/src/engine/export.rs diff --git a/lib/compiler/src/engine/export.rs b/lib/compiler/src/engine/export.rs deleted file mode 100644 index 2fc80458c20..00000000000 --- a/lib/compiler/src/engine/export.rs +++ /dev/null @@ -1,166 +0,0 @@ -use std::sync::Arc; -use wasmer_vm::{ImportInitializerFuncPtr, VMExtern, VMFunction, VMGlobal, VMMemory, VMTable}; - -/// The value of an export passed from one instance to another. -#[derive(Debug, Clone)] -pub enum Export { - /// A function export value. - Function(ExportFunction), - - /// A table export value. - Table(VMTable), - - /// A memory export value. - Memory(VMMemory), - - /// A global export value. - Global(VMGlobal), -} - -impl From for VMExtern { - fn from(other: Export) -> Self { - match other { - Export::Function(ExportFunction { vm_function, .. }) => Self::Function(vm_function), - Export::Memory(vm_memory) => Self::Memory(vm_memory), - Export::Table(vm_table) => Self::Table(vm_table), - Export::Global(vm_global) => Self::Global(vm_global), - } - } -} - -impl From for Export { - fn from(other: VMExtern) -> Self { - match other { - VMExtern::Function(vm_function) => Self::Function(ExportFunction { - vm_function, - metadata: None, - }), - VMExtern::Memory(vm_memory) => Self::Memory(vm_memory), - VMExtern::Table(vm_table) => Self::Table(vm_table), - VMExtern::Global(vm_global) => Self::Global(vm_global), - } - } -} - -/// Extra metadata about `ExportFunction`s. -/// -/// The metadata acts as a kind of manual virtual dispatch. We store the -/// user-supplied `WasmerEnv` as a void pointer and have methods on it -/// that have been adapted to accept a void pointer. -/// -/// This struct owns the original `host_env`, thus when it gets dropped -/// it calls the `drop` function on it. -#[derive(Debug, PartialEq)] -pub struct ExportFunctionMetadata { - /// This field is stored here to be accessible by `Drop`. - /// - /// At the time it was added, it's not accessed anywhere outside of - /// the `Drop` implementation. This field is the "master copy" of the env, - /// that is, the original env passed in by the user. Every time we create - /// an `Instance` we clone this with the `host_env_clone_fn` field. - /// - /// Thus, we only bother to store the master copy at all here so that - /// we can free it. - /// - /// See `wasmer_vm::export::VMFunction::vmctx` for the version of - /// this pointer that is used by the VM when creating an `Instance`. - pub(crate) host_env: *mut std::ffi::c_void, - - /// Function pointer to `WasmerEnv::init_with_instance(&mut self, instance: &Instance)`. - /// - /// This function is called to finish setting up the environment after - /// we create the `api::Instance`. - // This one is optional for now because dynamic host envs need the rest - // of this without the init fn - pub(crate) import_init_function_ptr: Option, - - /// A function analogous to `Clone::clone` that returns a leaked `Box`. - pub(crate) host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void, - - /// The destructor to free the host environment. - /// - /// # Safety - /// - This function should only be called in when properly synchronized. - /// For example, in the `Drop` implementation of this type. - pub(crate) host_env_drop_fn: unsafe fn(*mut std::ffi::c_void), -} - -/// This can be `Send` because `host_env` comes from `WasmerEnv` which is -/// `Send`. Therefore all operations should work on any thread. -unsafe impl Send for ExportFunctionMetadata {} -/// This data may be shared across threads, `drop` is an unsafe function -/// pointer, so care must be taken when calling it. -unsafe impl Sync for ExportFunctionMetadata {} - -impl ExportFunctionMetadata { - /// Create an `ExportFunctionMetadata` type with information about - /// the exported function. - /// - /// # Safety - /// - the `host_env` must be `Send`. - /// - all function pointers must work on any thread. - pub unsafe fn new( - host_env: *mut std::ffi::c_void, - import_init_function_ptr: Option, - host_env_clone_fn: fn(*mut std::ffi::c_void) -> *mut std::ffi::c_void, - host_env_drop_fn: fn(*mut std::ffi::c_void), - ) -> Self { - Self { - host_env, - import_init_function_ptr, - host_env_clone_fn, - host_env_drop_fn, - } - } -} - -// We have to free `host_env` here because we always clone it before using it -// so all the `host_env`s freed at the `Instance` level won't touch the original. -impl Drop for ExportFunctionMetadata { - fn drop(&mut self) { - if !self.host_env.is_null() { - // # Safety - // - This is correct because we know no other references - // to this data can exist if we're dropping it. - unsafe { - (self.host_env_drop_fn)(self.host_env); - } - } - } -} - -/// A function export value with an extra function pointer to initialize -/// host environments. -#[derive(Debug, Clone, PartialEq)] -pub struct ExportFunction { - /// The VM function, containing most of the data. - pub vm_function: VMFunction, - /// Contains functions necessary to create and initialize host envs - /// with each `Instance` as well as being responsible for the - /// underlying memory of the host env. - pub metadata: Option>, -} - -impl From for Export { - fn from(func: ExportFunction) -> Self { - Self::Function(func) - } -} - -impl From for Export { - fn from(table: VMTable) -> Self { - Self::Table(table) - } -} - -impl From for Export { - fn from(memory: VMMemory) -> Self { - Self::Memory(memory) - } -} - -impl From for Export { - fn from(global: VMGlobal) -> Self { - Self::Global(global) - } -} From 274aa3e1671dfd6c8cc2b20df272e519a29ab352 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Fri, 1 Jul 2022 10:33:43 +0200 Subject: [PATCH 19/24] Migrated al examples to new Context API --- examples/compiler_cranelift.rs | 7 ++-- examples/compiler_llvm.rs | 7 ++-- examples/compiler_singlepass.rs | 7 ++-- examples/early_exit.rs | 16 +++++---- examples/engine_headless.rs | 6 ++-- examples/engine_universal.rs | 7 ++-- examples/errors.rs | 11 ++++--- examples/exports_function.rs | 11 ++++--- examples/exports_global.rs | 37 +++++++++++---------- examples/exports_memory.rs | 26 ++++++++------- examples/features.rs | 7 ++-- examples/hello_world.rs | 2 +- examples/imports_exports.rs | 19 ++++++----- examples/imports_function.rs | 22 +++++++------ examples/imports_function_env.rs | 39 +++++++++++++--------- examples/imports_global.rs | 45 ++++++++++++------------- examples/instance.rs | 13 ++++---- examples/memory.rs | 38 +++++++++++---------- examples/metering.rs | 27 ++++++++------- examples/table.rs | 55 ++++++++++++++++--------------- examples/tunables_limit_memory.rs | 22 +++++-------- examples/wasi.rs | 15 ++++++--- examples/wasi_pipes.rs | 14 +++++--- 23 files changed, 249 insertions(+), 204 deletions(-) diff --git a/examples/compiler_cranelift.rs b/examples/compiler_cranelift.rs index f19b7ce8191..8c6aff08dfa 100644 --- a/examples/compiler_cranelift.rs +++ b/examples/compiler_cranelift.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -34,6 +34,7 @@ fn main() -> Result<(), Box> { // Create the store let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -44,14 +45,14 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; let sum = instance.exports.get_function("sum")?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/compiler_llvm.rs b/examples/compiler_llvm.rs index c62a1102064..b762443c415 100644 --- a/examples/compiler_llvm.rs +++ b/examples/compiler_llvm.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_llvm::LLVM; @@ -34,6 +34,7 @@ fn main() -> Result<(), Box> { // Create the store let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -44,14 +45,14 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; let sum = instance.exports.get_function("sum")?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/compiler_singlepass.rs b/examples/compiler_singlepass.rs index 39d12551c0d..2b7f87bea99 100644 --- a/examples/compiler_singlepass.rs +++ b/examples/compiler_singlepass.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_singlepass::Singlepass; @@ -34,6 +34,7 @@ fn main() -> Result<(), Box> { // Create the store let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -44,14 +45,14 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; let sum = instance.exports.get_function("sum")?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/early_exit.rs b/examples/early_exit.rs index 0206be52c2b..9e2181cfd9b 100644 --- a/examples/early_exit.rs +++ b/examples/early_exit.rs @@ -16,7 +16,9 @@ use anyhow::bail; use std::fmt; -use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, TypedFunction}; +use wasmer::{ + imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TypedFunction, +}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -56,13 +58,14 @@ fn main() -> anyhow::Result<()> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. let module = Module::new(&store, wasm_bytes)?; // We declare the host function that we'll use to terminate execution. - fn early_exit() -> Result<(), ExitCode> { + fn early_exit(_ctx: ContextMut<()>) -> Result<(), ExitCode> { // This is where it happens. Err(ExitCode(1)) } @@ -70,22 +73,23 @@ fn main() -> anyhow::Result<()> { // Create an import object. let import_object = imports! { "env" => { - "early_exit" => Function::new_native(&store, early_exit), + "early_exit" => Function::new_native(&mut ctx, early_exit), } }; println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // // Get the `run` function which we'll use as our entrypoint. println!("Calling `run` function..."); - let run_func: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function("run")?; + let run_func: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut ctx, "run")?; // When we call a function it can either succeed or fail. We expect it to fail. - match run_func.call(1, 7) { + match run_func.call(&mut ctx, 1, 7) { Ok(result) => { bail!( "Expected early termination with `ExitCode`, found: {}", diff --git a/examples/engine_headless.rs b/examples/engine_headless.rs index 3c0af060e68..4d84f0e38ae 100644 --- a/examples/engine_headless.rs +++ b/examples/engine_headless.rs @@ -47,6 +47,7 @@ use tempfile::NamedTempFile; use wasmer::imports; use wasmer::wat2wasm; +use wasmer::Context; use wasmer::Instance; use wasmer::Module; use wasmer::Store; @@ -106,6 +107,7 @@ fn main() -> Result<(), Box> { // We create a headless Universal engine. let engine = Universal::headless().engine(); let store = Store::new_with_engine(&engine); + let mut ctx = Context::new(&store, ()); println!("Deserializing module..."); // Here we go. @@ -125,12 +127,12 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; println!("Calling `sum` function..."); // The Wasm module exports a function called `sum`. let sum = instance.exports.get_function("sum")?; - let results = sum.call(&[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/engine_universal.rs b/examples/engine_universal.rs index 530449c0df2..819879669cb 100644 --- a/examples/engine_universal.rs +++ b/examples/engine_universal.rs @@ -18,7 +18,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -53,6 +53,7 @@ fn main() -> Result<(), Box> { // Create a store, that holds the engine. let store = Store::new_with_engine(&engine); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Here we go. @@ -72,12 +73,12 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // And here we go again. Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; println!("Calling `sum` function..."); // The Wasm module exports a function called `sum`. let sum = instance.exports.get_function("sum")?; - let results = sum.call(&[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/errors.rs b/examples/errors.rs index a9b2d93ed65..cf701dd1fb7 100644 --- a/examples/errors.rs +++ b/examples/errors.rs @@ -13,7 +13,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -40,6 +40,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -50,7 +51,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // @@ -59,14 +60,14 @@ fn main() -> Result<(), Box> { // produce an error. // // Let's get it. - let div_by_zero = instance + let div_by_zero: TypedFunction<(), i32> = instance .exports .get_function("div_by_zero")? - .native::<(), i32>()?; + .native(&mut ctx)?; println!("Calling `div_by_zero` function..."); // Let's call the `div_by_zero` exported function. - let result = div_by_zero.call(); + let result = div_by_zero.call(&mut ctx); // When we call a function it can either succeed or fail. We expect it to fail. match result { diff --git a/examples/exports_function.rs b/examples/exports_function.rs index bf873061799..4ab86beac7f 100644 --- a/examples/exports_function.rs +++ b/examples/exports_function.rs @@ -17,7 +17,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -41,6 +41,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -51,7 +52,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // @@ -73,7 +74,7 @@ fn main() -> Result<(), Box> { // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. let args = [Value::I32(1), Value::I32(2)]; - let result = sum.call(&args)?; + let result = sum.call(&mut ctx, &args)?; println!("Results: {:?}", result); assert_eq!(result.to_vec(), vec![Value::I32(3)]); @@ -86,13 +87,13 @@ fn main() -> Result<(), Box> { // `Rets`, respectively for the parameters and the results. If // those values don't match the exported function signature, an // error will be raised. - let sum_native = sum.native::<(i32, i32), i32>()?; + let sum_native: TypedFunction<(i32, i32), i32> = sum.native(&mut ctx)?; println!("Calling `sum` function (natively)..."); // Let's call the `sum` exported function. The parameters are // statically typed Rust values of type `i32` and `i32`. The // result, in this case particular case, in a unit of type `i32`. - let result = sum_native.call(3, 4)?; + let result = sum_native.call(&mut ctx, 3, 4)?; println!("Results: {:?}", result); assert_eq!(result, 7); diff --git a/examples/exports_global.rs b/examples/exports_global.rs index 3aaa1035783..19687fb3209 100644 --- a/examples/exports_global.rs +++ b/examples/exports_global.rs @@ -15,7 +15,9 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Mutability, Store, Type, Value}; +use wasmer::{ + imports, wat2wasm, Context, Instance, Module, Mutability, Store, Type, TypedFunction, Value, +}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -39,6 +41,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -49,7 +52,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // @@ -70,8 +73,8 @@ fn main() -> Result<(), Box> { println!("Getting globals types information..."); // Let's get the globals types. The results are `GlobalType`s. - let one_type = one.ty(); - let some_type = some.ty(); + let one_type = one.ty(&mut ctx); + let some_type = some.ty(&mut ctx); println!("`one` type: {:?} {:?}", one_type.mutability, one_type.ty); assert_eq!(one_type.mutability, Mutability::Const); @@ -88,13 +91,11 @@ fn main() -> Result<(), Box> { // // We will use an exported function for the `one` global // and the Global API for `some`. - let get_one = instance - .exports - .get_function("get_one")? - .native::<(), f32>()?; + let get_one: TypedFunction<(), f32> = + instance.exports.get_function("get_one")?.native(&mut ctx)?; - let one_value = get_one.call()?; - let some_value = some.get(); + let one_value = get_one.call(&mut ctx)?; + let some_value = some.get(&mut ctx); println!("`one` value: {:?}", one_value); assert_eq!(one_value, 1.0); @@ -105,13 +106,13 @@ fn main() -> Result<(), Box> { println!("Setting global values..."); // Trying to set the value of a immutable global (`const`) // will result in a `RuntimeError`. - let result = one.set(Value::F32(42.0)); + let result = one.set(&mut ctx, Value::F32(42.0)); assert_eq!( result.expect_err("Expected an error").message(), "Attempted to set an immutable global" ); - let one_result = one.get(); + let one_result = one.get(&mut ctx); println!("`one` value after `set`: {:?}", one_result); assert_eq!(one_result, Value::F32(1.0)); @@ -120,17 +121,17 @@ fn main() -> Result<(), Box> { // 2. Using the Global API directly. // // We will use both for the `some` global. - let set_some = instance + let set_some: TypedFunction = instance .exports .get_function("set_some")? - .native::()?; - set_some.call(21.0)?; - let some_result = some.get(); + .native(&mut ctx)?; + set_some.call(&mut ctx, 21.0)?; + let some_result = some.get(&mut ctx); println!("`some` value after `set_some`: {:?}", some_result); assert_eq!(some_result, Value::F32(21.0)); - some.set(Value::F32(42.0))?; - let some_result = some.get(); + some.set(&mut ctx, Value::F32(42.0))?; + let some_result = some.get(&mut ctx); println!("`some` value after `set`: {:?}", some_result); assert_eq!(some_result, Value::F32(42.0)); diff --git a/examples/exports_memory.rs b/examples/exports_memory.rs index 0f7cb533a0e..f8f5b29feb7 100644 --- a/examples/exports_memory.rs +++ b/examples/exports_memory.rs @@ -11,7 +11,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store, WasmPtr}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction, WasmPtr}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -38,6 +38,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -48,11 +49,10 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; - let load = instance - .exports - .get_typed_function::<(), (WasmPtr, i32)>("load")?; + let load: TypedFunction<(), (WasmPtr, i32)> = + instance.exports.get_typed_function(&mut ctx, "load")?; // Here we go. // @@ -64,15 +64,15 @@ fn main() -> Result<(), Box> { // // The first thing we might be intersted in is the size of the memory. // Let's get it! - println!("Memory size (pages) {:?}", memory.size()); - println!("Memory size (bytes) {:?}", memory.data_size()); + println!("Memory size (pages) {:?}", memory.size(&mut ctx)); + println!("Memory size (bytes) {:?}", memory.data_size(&mut ctx)); // Oh! Wait, before reading the contents, we need to know // where to find what we are looking for. // // Fortunately, the Wasm module exports a `load` function // which will tell us the offset and length of the string. - let (ptr, length) = load.call()?; + let (ptr, length) = load.call(&mut ctx)?; println!("String offset: {:?}", ptr.offset()); println!("String length: {:?}", length); @@ -80,7 +80,9 @@ fn main() -> Result<(), Box> { // // We will get bytes out of the memory so we need to // decode them into a string. - let str = ptr.read_utf8_string(memory, length as u32).unwrap(); + let str = ptr + .read_utf8_string(&mut ctx, memory, length as u32) + .unwrap(); println!("Memory contents: {:?}", str); // What about changing the contents of the memory with a more @@ -89,7 +91,7 @@ fn main() -> Result<(), Box> { // To do that, we'll make a slice from our pointer and change the content // of each element. let new_str = b"Hello, Wasmer!"; - let values = ptr.slice(memory, new_str.len() as u32).unwrap(); + let values = ptr.slice(&mut ctx, memory, new_str.len() as u32).unwrap(); for i in 0..new_str.len() { values.index(i as u64).write(new_str[i]).unwrap(); } @@ -101,7 +103,9 @@ fn main() -> Result<(), Box> { // before. println!("New string length: {:?}", new_str.len()); - let str = ptr.read_utf8_string(memory, new_str.len() as u32).unwrap(); + let str = ptr + .read_utf8_string(&mut ctx, memory, new_str.len() as u32) + .unwrap(); println!("New memory contents: {:?}", str); // Much better, don't you think? diff --git a/examples/features.rs b/examples/features.rs index f60d24f17d1..d4f8058ce60 100644 --- a/examples/features.rs +++ b/examples/features.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Features, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Context, Features, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -40,15 +40,16 @@ fn main() -> anyhow::Result<()> { // Now, let's define the store, and compile the module. let store = Store::new_with_engine(&engine.engine()); + let mut ctx = Context::new(&store, ()); let module = Module::new(&store, wasm_bytes)?; // Finally, let's instantiate the module, and execute something // :-). let import_object = imports! {}; - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; let swap = instance.exports.get_function("swap")?; - let results = swap.call(&[Value::I32(1), Value::I64(2)])?; + let results = swap.call(&mut ctx, &[Value::I32(1), Value::I64(2)])?; assert_eq!(results.to_vec(), vec![Value::I64(2), Value::I32(1)]); diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 21b16c9f367..39ea01df73b 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -58,7 +58,7 @@ fn main() -> anyhow::Result<()> { // We define a function to act as our "env" "say_hello" function imported in the // Wasm program above. - fn say_hello_world(ctx: ContextMut<'_, ()>) { + fn say_hello_world(_ctx: ContextMut<'_, ()>) { println!("Hello, world!") } diff --git a/examples/imports_exports.rs b/examples/imports_exports.rs index 2cde8af885b..fc07e22a1eb 100644 --- a/examples/imports_exports.rs +++ b/examples/imports_exports.rs @@ -16,8 +16,8 @@ //! Ready? use wasmer::{ - imports, wat2wasm, Function, FunctionType, Global, Instance, Memory, Module, Store, Table, - Type, Value, + imports, wat2wasm, Context, Function, FunctionType, Global, Instance, Memory, Module, Store, + Table, Type, Value, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -45,6 +45,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -59,12 +60,12 @@ fn main() -> Result<(), Box> { // covered in more detail in other examples. println!("Creating the imported function..."); let host_function_signature = FunctionType::new(vec![], vec![Type::I32]); - let host_function = Function::new(&store, &host_function_signature, |_args| { + let host_function = Function::new(&mut ctx, &host_function_signature, |_ctx, _args| { Ok(vec![Value::I32(42)]) }); println!("Creating the imported global..."); - let host_global = Global::new(&store, Value::I32(42)); + let host_global = Global::new(&mut ctx, Value::I32(42)); // Create an import object. // @@ -89,7 +90,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // @@ -102,19 +103,19 @@ fn main() -> Result<(), Box> { // Let's get them. println!("Getting the exported function..."); let function = instance.exports.get::("guest_function")?; - println!("Got exported function of type: {:?}", function.ty()); + println!("Got exported function of type: {:?}", function.ty(&mut ctx)); println!("Getting the exported global..."); let global = instance.exports.get::("guest_global")?; - println!("Got exported global of type: {:?}", global.ty()); + println!("Got exported global of type: {:?}", global.ty(&mut ctx)); println!("Getting the exported memory..."); let memory = instance.exports.get::("guest_memory")?; - println!("Got exported memory of type: {:?}", memory.ty()); + println!("Got exported memory of type: {:?}", memory.ty(&mut ctx)); println!("Getting the exported table..."); let table = instance.exports.get::
("guest_table")?; - println!("Got exported table of type: {:?}", table.ty()); + println!("Got exported table of type: {:?}", table.ty(&mut ctx)); Ok(()) } diff --git a/examples/imports_function.rs b/examples/imports_function.rs index 919debec005..ca1bdebf39d 100644 --- a/examples/imports_function.rs +++ b/examples/imports_function.rs @@ -17,7 +17,10 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Function, FunctionType, Instance, Module, Store, Type, Value}; +use wasmer::{ + imports, wat2wasm, Context, ContextMut, Function, FunctionType, Instance, Module, Store, Type, + TypedFunction, Value, +}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -43,6 +46,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -50,7 +54,7 @@ fn main() -> Result<(), Box> { // Create the functions let multiply_dynamic_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let multiply_dynamic = Function::new(&store, &multiply_dynamic_signature, |args| { + let multiply_dynamic = Function::new(&mut ctx, &multiply_dynamic_signature, |_ctx, args| { println!("Calling `multiply_dynamic`..."); let result = args[0].unwrap_i32() * 2; @@ -60,7 +64,7 @@ fn main() -> Result<(), Box> { Ok(vec![Value::I32(result)]) }); - fn multiply(a: i32) -> i32 { + fn multiply(_ctx: ContextMut<()>, a: i32) -> i32 { println!("Calling `multiply_native`..."); let result = a * 3; @@ -68,7 +72,7 @@ fn main() -> Result<(), Box> { result } - let multiply_native = Function::new_native(&store, multiply); + let multiply_native = Function::new_native(&mut ctx, multiply); // Create an import object. let import_object = imports! { @@ -80,20 +84,18 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // // The Wasm module exports a function called `sum`. Let's get it. - let sum = instance - .exports - .get_function("sum")? - .native::<(i32, i32), i32>()?; + let sum: TypedFunction<(i32, i32), i32> = + instance.exports.get_function("sum")?.native(&mut ctx)?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. It will call each // of the imported functions. - let result = sum.call(1, 2)?; + let result = sum.call(&mut ctx, 1, 2)?; println!("Results of `sum`: {:?}", result); assert_eq!(result, 8); diff --git a/examples/imports_function_env.rs b/examples/imports_function_env.rs index b1b534e033f..9f0fcafda96 100644 --- a/examples/imports_function_env.rs +++ b/examples/imports_function_env.rs @@ -20,7 +20,9 @@ //! Ready? use std::sync::{Arc, Mutex}; -use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, WasmerEnv}; +use wasmer::{ + imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TypedFunction, +}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -63,47 +65,54 @@ fn main() -> Result<(), Box> { let shared_counter: Arc> = Arc::new(Mutex::new(0)); // Once we have our counter we'll wrap it inside en `Env` which we'll pass - // to our imported functions. + // to our imported functionsvia the Context. // // This struct may have been anything. The only constraint is it must be // possible to know the size of the `Env` at compile time (i.e it has to - // implement the `Sized` trait) and that it implement the `WasmerEnv` trait. - // We derive a default implementation of `WasmerEnv` here. - #[derive(WasmerEnv, Clone)] + // implement the `Sized` trait). + // The Env is then accessed using `data()` or `data_mut()` method. + #[derive(Clone)] struct Env { counter: Arc>, } // Create the functions - fn get_counter(env: &Env) -> i32 { - *env.counter.lock().unwrap() + fn get_counter(ctx: ContextMut) -> i32 { + *ctx.data().counter.lock().unwrap() } - fn add_to_counter(env: &Env, add: i32) -> i32 { - let mut counter_ref = env.counter.lock().unwrap(); + fn add_to_counter(mut ctx: ContextMut, add: i32) -> i32 { + let mut counter_ref = ctx.data_mut().counter.lock().unwrap(); *counter_ref += add; *counter_ref } + let mut ctx = Context::new( + &store, + Env { + counter: shared_counter.clone(), + }, + ); + // Create an import object. let import_object = imports! { "env" => { - "get_counter" => Function::new_native_with_env(&store, Env { counter: shared_counter.clone() }, get_counter), - "add_to_counter" => Function::new_native_with_env(&store, Env { counter: shared_counter.clone() }, add_to_counter), + "get_counter" => Function::new_native(&mut ctx, get_counter), + "add_to_counter" => Function::new_native(&mut ctx, add_to_counter), } }; println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // // The Wasm module exports a function called `increment_counter_loop`. Let's get it. - let increment_counter_loop = instance + let increment_counter_loop: TypedFunction = instance .exports .get_function("increment_counter_loop")? - .native::()?; + .native(&mut ctx)?; let counter_value: i32 = *shared_counter.lock().unwrap(); println!("Initial ounter value: {:?}", counter_value); @@ -112,7 +121,7 @@ fn main() -> Result<(), Box> { // Let's call the `increment_counter_loop` exported function. // // It will loop five times thus incrementing our counter five times. - let result = increment_counter_loop.call(5)?; + let result = increment_counter_loop.call(&mut ctx, 5)?; let counter_value: i32 = *shared_counter.lock().unwrap(); println!("New counter value (host): {:?}", counter_value); diff --git a/examples/imports_global.rs b/examples/imports_global.rs index af91acf83e0..7e6eaaddb5f 100644 --- a/examples/imports_global.rs +++ b/examples/imports_global.rs @@ -15,7 +15,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Global, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Context, Global, Instance, Module, Store, TypedFunction, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -39,14 +39,15 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. let module = Module::new(&store, wasm_bytes)?; // Create the globals - let some = Global::new(&store, Value::F32(1.0)); - let other = Global::new_mut(&store, Value::F32(2.0)); + let some = Global::new(&mut ctx, Value::F32(1.0)); + let other = Global::new_mut(&mut ctx, Value::F32(2.0)); // Create an import object. // We add the two required globals in the `env` namespace. @@ -59,57 +60,57 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Here we go. // // The Wasm module only imports some globals. We'll have to interact // with them either using the Global API or exported functions. - let get_some = instance + let get_some: TypedFunction<(), f32> = instance .exports .get_function("get_some")? - .native::<(), f32>()?; - let get_other = instance + .native(&mut ctx)?; + let get_other: TypedFunction<(), f32> = instance .exports .get_function("get_other")? - .native::<(), f32>()?; + .native(&mut ctx)?; - let some_result = get_some.call()?; - let other_result = get_other.call()?; + let some_result = get_some.call(&mut ctx)?; + let other_result = get_other.call(&mut ctx)?; println!("some value (via `get_some`): {:?}", some_result); - println!("some value (via Global API): {:?}", some.get()); + println!("some value (via Global API): {:?}", some.get(&mut ctx)); println!("other value (via `get_other`): {:?}", other_result); - println!("other value (via Global API): {:?}", other.get()); + println!("other value (via Global API): {:?}", other.get(&mut ctx)); - assert_eq!(some_result, some.get().f32().unwrap()); - assert_eq!(other_result, other.get().f32().unwrap()); + assert_eq!(some_result, some.get(&mut ctx).f32().unwrap()); + assert_eq!(other_result, other.get(&mut ctx).f32().unwrap()); println!("Setting global values..."); // Trying to set the value of a immutable global (`const`) // will result in a `RuntimeError`. - let result = some.set(Value::F32(42.0)); + let result = some.set(&mut ctx, Value::F32(42.0)); assert_eq!( result.expect_err("Expected an error").message(), "Attempted to set an immutable global" ); - other.set(Value::F32(21.0))?; - let other_result = other.get(); + other.set(&mut ctx, Value::F32(21.0))?; + let other_result = other.get(&mut ctx); println!("other value after `set`: {:?}", other_result); assert_eq!(other_result, Value::F32(21.0)); println!("Altering global values through exported functions..."); // Changes made to global through exported functions will // be reflected on the host side. - let set_other = instance + let set_other: TypedFunction = instance .exports .get_function("set_other")? - .native::()?; - set_other.call(42.0)?; + .native(&mut ctx)?; + set_other.call(&mut ctx, 42.0)?; - println!("other value (via Global API): {:?}", other.get()); - assert_eq!(other.get(), Value::F32(42.0)); + println!("other value (via Global API): {:?}", other.get(&mut ctx)); + assert_eq!(other.get(&mut ctx), Value::F32(42.0)); Ok(()) } diff --git a/examples/instance.rs b/examples/instance.rs index 66404032e9b..5e8a9de09ac 100644 --- a/examples/instance.rs +++ b/examples/instance.rs @@ -14,7 +14,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Instance, Module, Store}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -40,6 +40,7 @@ fn main() -> Result<(), Box> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -50,7 +51,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // We now have an instance ready to be used. // @@ -60,13 +61,11 @@ fn main() -> Result<(), Box> { // Here we are retrieving the exported function. We won't go into details here // as the main focus of this example is to show how to create an instance out // of a Wasm module and have basic interactions with it. - let add_one = instance - .exports - .get_function("add_one")? - .native::()?; + let add_one: TypedFunction = + instance.exports.get_function("add_one")?.native(&mut ctx)?; println!("Calling `add_one` function..."); - let result = add_one.call(1)?; + let result = add_one.call(&mut ctx, 1)?; println!("Results of `add_one`: {:?}", result); assert_eq!(result, 2); diff --git a/examples/memory.rs b/examples/memory.rs index 72b29c892f0..66fa88f8e77 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -15,7 +15,7 @@ //! Ready? use std::mem; -use wasmer::{imports, wat2wasm, Bytes, Instance, Module, Pages, Store, TypedFunction}; +use wasmer::{imports, wat2wasm, Bytes, Context, Instance, Module, Pages, Store, TypedFunction}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -58,6 +58,7 @@ fn main() -> anyhow::Result<()> { // the default provided by Wasmer. // You can use `Store::default()` for that. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -68,14 +69,17 @@ fn main() -> anyhow::Result<()> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // The module exports some utility functions, let's get them. // // These function will be used later in this example. - let mem_size: TypedFunction<(), i32> = instance.exports.get_typed_function("mem_size")?; - let get_at: TypedFunction = instance.exports.get_typed_function("get_at")?; - let set_at: TypedFunction<(i32, i32), ()> = instance.exports.get_typed_function("set_at")?; + let mem_size: TypedFunction<(), i32> = + instance.exports.get_typed_function(&mut ctx, "mem_size")?; + let get_at: TypedFunction = + instance.exports.get_typed_function(&mut ctx, "get_at")?; + let set_at: TypedFunction<(i32, i32), ()> = + instance.exports.get_typed_function(&mut ctx, "set_at")?; let memory = instance.exports.get_memory("memory")?; // We now have an instance ready to be used. @@ -89,15 +93,15 @@ fn main() -> anyhow::Result<()> { // The size in bytes can be found either by querying its pages or by // querying the memory directly. println!("Querying memory size..."); - assert_eq!(memory.size(), Pages::from(1)); - assert_eq!(memory.size().bytes(), Bytes::from(65536 as usize)); - assert_eq!(memory.data_size(), 65536); + assert_eq!(memory.size(&mut ctx), Pages::from(1)); + assert_eq!(memory.size(&mut ctx).bytes(), Bytes::from(65536 as usize)); + assert_eq!(memory.data_size(&mut ctx), 65536); // Sometimes, the guest module may also export a function to let you // query the memory. Here we have a `mem_size` function, let's try it: - let result = mem_size.call()?; + let result = mem_size.call(&mut ctx)?; println!("Memory size: {:?}", result); - assert_eq!(Pages::from(result as u32), memory.size()); + assert_eq!(Pages::from(result as u32), memory.size(&mut ctx)); // Now that we know the size of our memory, it's time to see how wa // can change this. @@ -106,9 +110,9 @@ fn main() -> anyhow::Result<()> { // see how we can do that: println!("Growing memory..."); // Here we are requesting two more pages for our memory. - memory.grow(2)?; - assert_eq!(memory.size(), Pages::from(3)); - assert_eq!(memory.data_size(), 65536 * 3); + memory.grow(&mut ctx, 2)?; + assert_eq!(memory.size(&mut ctx), Pages::from(3)); + assert_eq!(memory.data_size(&mut ctx), 65536 * 3); // Now that we know how to query and adjust the size of the memory, // let's see how wa can write to it or read from it. @@ -118,9 +122,9 @@ fn main() -> anyhow::Result<()> { // addresses to write and read a value. let mem_addr = 0x2220; let val = 0xFEFEFFE; - set_at.call(mem_addr, val)?; + set_at.call(&mut ctx, mem_addr, val)?; - let result = get_at.call(mem_addr)?; + let result = get_at.call(&mut ctx, mem_addr)?; println!("Value at {:#x?}: {:?}", mem_addr, result); assert_eq!(result, val); @@ -129,9 +133,9 @@ fn main() -> anyhow::Result<()> { let page_size = 0x1_0000; let mem_addr = (page_size * 2) - mem::size_of_val(&val) as i32; let val = 0xFEA09; - set_at.call(mem_addr, val)?; + set_at.call(&mut ctx, mem_addr, val)?; - let result = get_at.call(mem_addr)?; + let result = get_at.call(&mut ctx, mem_addr)?; println!("Value at {:#x?}: {:?}", mem_addr, result); assert_eq!(result, val); diff --git a/examples/metering.rs b/examples/metering.rs index 27d7248409f..613e2cab446 100644 --- a/examples/metering.rs +++ b/examples/metering.rs @@ -18,7 +18,7 @@ use anyhow::bail; use std::sync::Arc; use wasmer::wasmparser::Operator; use wasmer::CompilerConfig; -use wasmer::{imports, wat2wasm, Instance, Module, Store}; +use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; use wasmer_middlewares::{ @@ -71,6 +71,7 @@ fn main() -> anyhow::Result<()> { // We use our previously create compiler configuration // with the Universal engine. let store = Store::new_with_engine(&Universal::new(compiler_config).engine()); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -81,19 +82,17 @@ fn main() -> anyhow::Result<()> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // We now have an instance ready to be used. // // Our module exports a single `add_one` function. We want to // measure the cost of executing this function. - let add_one = instance - .exports - .get_function("add_one")? - .native::()?; + let add_one: TypedFunction = + instance.exports.get_function("add_one")?.native(&mut ctx)?; println!("Calling `add_one` function once..."); - add_one.call(1)?; + add_one.call(&mut ctx, 1)?; // As you can see here, after the first call we have 6 remaining points. // @@ -101,7 +100,7 @@ fn main() -> anyhow::Result<()> { // * `local.get $value` is a `Operator::LocalGet` which costs 1 point; // * `i32.const` is a `Operator::I32Const` which costs 1 point; // * `i32.add` is a `Operator::I32Add` which costs 2 points. - let remaining_points_after_first_call = get_remaining_points(&instance); + let remaining_points_after_first_call = get_remaining_points(&mut ctx, &instance); assert_eq!( remaining_points_after_first_call, MeteringPoints::Remaining(6) @@ -113,11 +112,11 @@ fn main() -> anyhow::Result<()> { ); println!("Calling `add_one` function twice..."); - add_one.call(1)?; + add_one.call(&mut ctx, 1)?; // We spent 4 more points with the second call. // We have 2 remaining points. - let remaining_points_after_second_call = get_remaining_points(&instance); + let remaining_points_after_second_call = get_remaining_points(&mut ctx, &instance); assert_eq!( remaining_points_after_second_call, MeteringPoints::Remaining(2) @@ -132,7 +131,7 @@ fn main() -> anyhow::Result<()> { // calling it a third time will fail: we already consume 8 // points, there are only two remaining. println!("Calling `add_one` function a third time..."); - match add_one.call(1) { + match add_one.call(&mut ctx, 1) { Ok(result) => { bail!( "Expected failure while calling `add_one`, found: {}", @@ -143,7 +142,7 @@ fn main() -> anyhow::Result<()> { println!("Calling `add_one` failed."); // Because the last needed more than the remaining points, we should have an error. - let remaining_points = get_remaining_points(&instance); + let remaining_points = get_remaining_points(&mut ctx, &instance); match remaining_points { MeteringPoints::Remaining(..) => { @@ -157,9 +156,9 @@ fn main() -> anyhow::Result<()> { // Now let's see how we can set a new limit... println!("Set new remaining points to 10"); let new_limit = 10; - set_remaining_points(&instance, new_limit); + set_remaining_points(&mut ctx, &instance, new_limit); - let remaining_points = get_remaining_points(&instance); + let remaining_points = get_remaining_points(&mut ctx, &instance); assert_eq!(remaining_points, MeteringPoints::Remaining(new_limit)); println!("Remaining points: {:?}", remaining_points); diff --git a/examples/table.rs b/examples/table.rs index ac73da0a12c..70e365a5069 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -1,11 +1,12 @@ use wasmer::{ - imports, wat2wasm, Function, Instance, Module, Store, TableType, Type, TypedFunction, Value, + imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TableType, Type, + TypedFunction, Value, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; /// A function we'll call through a table. -fn host_callback(arg1: i32, arg2: i32) -> i32 { +fn host_callback(_ctx: ContextMut<()>, arg1: i32, arg2: i32) -> i32 { arg1 + arg2 } @@ -52,20 +53,22 @@ fn main() -> anyhow::Result<()> { // We set up our store with an engine and a compiler. let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx = Context::new(&store, ()); // Then compile our Wasm. let module = Module::new(&store, wasm_bytes)?; let import_object = imports! {}; // And instantiate it with no imports. - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // We get our function that calls (i32, i32) -> i32 functions via table. // The first argument is the table index and the next 2 are the 2 arguments // to be passed to the function found in the table. - let call_via_table: TypedFunction<(i32, i32, i32), i32> = - instance.exports.get_typed_function("call_callback")?; + let call_via_table: TypedFunction<(i32, i32, i32), i32> = instance + .exports + .get_typed_function(&mut ctx, "call_callback")?; // And then call it with table index 1 and arguments 2 and 7. - let result = call_via_table.call(1, 2, 7)?; + let result = call_via_table.call(&mut ctx, 1, 2, 7)?; // Because it's the default function, we expect it to double each number and // then sum it, giving us 18. assert_eq!(result, 18); @@ -73,10 +76,10 @@ fn main() -> anyhow::Result<()> { // We then get the table from the instance. let guest_table = instance.exports.get_table("__indirect_function_table")?; // And demonstrate that it has the properties that we set in the Wasm. - assert_eq!(guest_table.size(), 3); + assert_eq!(guest_table.size(&mut ctx), 3); assert_eq!( - guest_table.ty(), - &TableType { + guest_table.ty(&mut ctx), + TableType { ty: Type::FuncRef, minimum: 3, maximum: Some(6) @@ -86,31 +89,31 @@ fn main() -> anyhow::Result<()> { // == Setting elements in a table == // We first construct a `Function` over our host_callback. - let func = Function::new_native(&store, host_callback); + let func = Function::new_native(&mut ctx, host_callback); // And set table index 1 of that table to the host_callback `Function`. - guest_table.set(1, func.into())?; + guest_table.set(&mut ctx, 1, func.into())?; // We then repeat the call from before but this time it will find the host function // that we put at table index 1. - let result = call_via_table.call(1, 2, 7)?; + let result = call_via_table.call(&mut ctx, 1, 2, 7)?; // And because our host function simply sums the numbers, we expect 9. assert_eq!(result, 9); // == Growing a table == // We again construct a `Function` over our host_callback. - let func = Function::new_native(&store, host_callback); + let func = Function::new_native(&mut ctx, host_callback); // And grow the table by 3 elements, filling in our host_callback in all the // new elements of the table. - let previous_size = guest_table.grow(3, func.into())?; + let previous_size = guest_table.grow(&mut ctx, 3, func.into())?; assert_eq!(previous_size, 3); - assert_eq!(guest_table.size(), 6); + assert_eq!(guest_table.size(&mut ctx), 6); assert_eq!( - guest_table.ty(), - &TableType { + guest_table.ty(&mut ctx), + TableType { ty: Type::FuncRef, minimum: 3, maximum: Some(6) @@ -118,8 +121,8 @@ fn main() -> anyhow::Result<()> { ); // Now demonstrate that the function we grew the table with is actually in the table. for table_index in 3..6 { - if let Value::FuncRef(Some(f)) = guest_table.get(table_index as _).unwrap() { - let result = f.call(&[Value::I32(1), Value::I32(9)])?; + if let Value::FuncRef(Some(f)) = guest_table.get(&mut ctx, table_index as _).unwrap() { + let result = f.call(&mut ctx, &[Value::I32(1), Value::I32(9)])?; assert_eq!(result[0], Value::I32(10)); } else { panic!("expected to find funcref in table!"); @@ -127,26 +130,26 @@ fn main() -> anyhow::Result<()> { } // Call function at index 0 to show that it's still the same. - let result = call_via_table.call(0, 2, 7)?; + let result = call_via_table.call(&mut ctx, 0, 2, 7)?; assert_eq!(result, 18); // Now overwrite index 0 with our host_callback. - let func = Function::new_native(&store, host_callback); - guest_table.set(0, func.into())?; + let func = Function::new_native(&mut ctx, host_callback); + guest_table.set(&mut ctx, 0, func.into())?; // And verify that it does what we expect. - let result = call_via_table.call(0, 2, 7)?; + let result = call_via_table.call(&mut ctx, 0, 2, 7)?; assert_eq!(result, 9); // Now demonstrate that the host and guest see the same table and that both // get the same result. for table_index in 3..6 { - if let Value::FuncRef(Some(f)) = guest_table.get(table_index as _).unwrap() { - let result = f.call(&[Value::I32(1), Value::I32(9)])?; + if let Value::FuncRef(Some(f)) = guest_table.get(&mut ctx, table_index as _).unwrap() { + let result = f.call(&mut ctx, &[Value::I32(1), Value::I32(9)])?; assert_eq!(result[0], Value::I32(10)); } else { panic!("expected to find funcref in table!"); } - let result = call_via_table.call(table_index, 1, 9)?; + let result = call_via_table.call(&mut ctx, table_index, 1, 9)?; assert_eq!(result, 10); } diff --git a/examples/tunables_limit_memory.rs b/examples/tunables_limit_memory.rs index 3e43cd9f7d5..9b4f4e1ebd7 100644 --- a/examples/tunables_limit_memory.rs +++ b/examples/tunables_limit_memory.rs @@ -1,11 +1,10 @@ use std::ptr::NonNull; -use std::sync::Arc; use wasmer::{ imports, vm::{self, MemoryError, MemoryStyle, TableStyle, VMMemoryDefinition, VMTableDefinition}, - wat2wasm, BaseTunables, Instance, Memory, MemoryType, Module, Pages, Store, TableType, Target, - Tunables, + wat2wasm, BaseTunables, Context, Instance, Memory, MemoryType, Module, Pages, Store, TableType, + Target, Tunables, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -86,7 +85,7 @@ impl Tunables for LimitingTunables { &self, ty: &MemoryType, style: &MemoryStyle, - ) -> Result, MemoryError> { + ) -> Result { let adjusted = self.adjust_memory(ty); self.validate_memory(&adjusted)?; self.base.create_host_memory(&adjusted, style) @@ -100,7 +99,7 @@ impl Tunables for LimitingTunables { ty: &MemoryType, style: &MemoryStyle, vm_definition_location: NonNull, - ) -> Result, MemoryError> { + ) -> Result { let adjusted = self.adjust_memory(ty); self.validate_memory(&adjusted)?; self.base @@ -110,11 +109,7 @@ impl Tunables for LimitingTunables { /// Create a table owned by the host given a [`TableType`] and a [`TableStyle`]. /// /// Delegated to base. - fn create_host_table( - &self, - ty: &TableType, - style: &TableStyle, - ) -> Result, String> { + fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result { self.base.create_host_table(ty, style) } @@ -126,7 +121,7 @@ impl Tunables for LimitingTunables { ty: &TableType, style: &TableStyle, vm_definition_location: NonNull, - ) -> Result, String> { + ) -> Result { self.base.create_vm_table(ty, style, vm_definition_location) } } @@ -151,6 +146,7 @@ fn main() -> Result<(), Box> { // Create a store, that holds the engine and our custom tunables let store = Store::new_with_tunables(&engine, tunables); + let mut ctx = Context::new(&store, ()); println!("Compiling module..."); let module = Module::new(&store, wasm_bytes)?; @@ -159,7 +155,7 @@ fn main() -> Result<(), Box> { let import_object = imports! {}; // Now at this point, our custom tunables are used - let instance = Instance::new(&module, &import_object)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; // Check what happened let mut memories: Vec = instance @@ -172,7 +168,7 @@ fn main() -> Result<(), Box> { let first_memory = memories.pop().unwrap(); println!("Memory of this instance: {:?}", first_memory); - assert_eq!(first_memory.ty().maximum.unwrap(), Pages(24)); + assert_eq!(first_memory.ty(&mut ctx).maximum.unwrap(), Pages(24)); Ok(()) } diff --git a/examples/wasi.rs b/examples/wasi.rs index 2b80cf7fc11..2eb77075e55 100644 --- a/examples/wasi.rs +++ b/examples/wasi.rs @@ -15,7 +15,7 @@ //! //! Ready? -use wasmer::{Instance, Module, Store}; +use wasmer::{AsContextMut, Context, Instance, Module, Store}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; use wasmer_wasi::WasiState; @@ -44,17 +44,24 @@ fn main() -> Result<(), Box> { // .args(&["world"]) // .env("KEY", "Value") .finalize()?; + // And now the context,using the newly created WasiEnv + let mut ctx = Context::new(&store, wasi_env.clone()); println!("Instantiating module with WASI imports..."); // Then, we get the import object related to our WASI // and attach it to the Wasm instance. - let import_object = wasi_env.import_object(&module)?; - let instance = Instance::new(&module, &import_object)?; + let import_object = wasi_env.import_object(&mut ctx.as_context_mut(), &module)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; + + println!("Attach WASI memory..."); + // Attach the memory export + let memory = instance.exports.get_memory("memory")?; + ctx.data_mut().set_memory(memory.clone()); println!("Call WASI `_start` function..."); // And we just call the `_start` function! let start = instance.exports.get_function("_start")?; - start.call(&[])?; + start.call(&mut ctx, &[])?; Ok(()) } diff --git a/examples/wasi_pipes.rs b/examples/wasi_pipes.rs index c4efec10a84..b5b8a750459 100644 --- a/examples/wasi_pipes.rs +++ b/examples/wasi_pipes.rs @@ -12,7 +12,7 @@ //! Ready? use std::io::{Read, Write}; -use wasmer::{Instance, Module, Store}; +use wasmer::{AsContextMut, Context, Instance, Module, Store}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; use wasmer_wasi::{Pipe, WasiState}; @@ -43,12 +43,18 @@ fn main() -> Result<(), Box> { .stdin(Box::new(input.clone())) .stdout(Box::new(output.clone())) .finalize()?; + let mut ctx = Context::new(&store, wasi_env.clone()); println!("Instantiating module with WASI imports..."); // Then, we get the import object related to our WASI // and attach it to the Wasm instance. - let import_object = wasi_env.import_object(&module)?; - let instance = Instance::new(&module, &import_object)?; + let import_object = wasi_env.import_object(&mut ctx.as_context_mut(), &module)?; + let instance = Instance::new(&mut ctx, &module, &import_object)?; + + println!("Attach WASI memory..."); + // Attach the memory export + let memory = instance.exports.get_memory("memory")?; + ctx.data_mut().set_memory(memory.clone()); let msg = "racecar go zoom"; println!("Writing \"{}\" to the WASI stdin...", msg); @@ -58,7 +64,7 @@ fn main() -> Result<(), Box> { println!("Call WASI `_start` function..."); // And we just call the `_start` function! let start = instance.exports.get_function("_start")?; - start.call(&[])?; + start.call(&mut ctx, &[])?; println!("Reading from the WASI stdout..."); From 62f07efb086fcd43b140d814b43c4fb025c9cdb7 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Fri, 1 Jul 2022 23:17:06 +0300 Subject: [PATCH 20/24] c-api: Add wasm_*_same functions to global,memory,table --- lib/api/src/sys/externals/global.rs | 8 ++++++++ lib/api/src/sys/externals/memory.rs | 8 ++++++++ lib/api/src/sys/externals/table.rs | 8 ++++++++ lib/c-api/src/wasm_c_api/externals/global.rs | 8 ++++++++ lib/c-api/src/wasm_c_api/externals/memory.rs | 8 ++++++++ lib/c-api/src/wasm_c_api/externals/table.rs | 8 ++++++++ lib/vm/src/context.rs | 8 ++++++++ 7 files changed, 56 insertions(+) diff --git a/lib/api/src/sys/externals/global.rs b/lib/api/src/sys/externals/global.rs index 5e4f2418403..627325f4d16 100644 --- a/lib/api/src/sys/externals/global.rs +++ b/lib/api/src/sys/externals/global.rs @@ -222,6 +222,14 @@ impl Global { } } +impl std::cmp::PartialEq for Global { + fn eq(&self, other: &Self) -> bool { + self.handle == other.handle + } +} + +impl std::cmp::Eq for Global {} + impl<'a> Exportable<'a> for Global { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 9434253defa..136e7620436 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -239,6 +239,14 @@ impl Memory { } } +impl std::cmp::PartialEq for Memory { + fn eq(&self, other: &Self) -> bool { + self.handle == other.handle + } +} + +impl std::cmp::Eq for Memory {} + impl<'a> Exportable<'a> for Memory { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { diff --git a/lib/api/src/sys/externals/table.rs b/lib/api/src/sys/externals/table.rs index d928cfd546b..9e2862b9bd5 100644 --- a/lib/api/src/sys/externals/table.rs +++ b/lib/api/src/sys/externals/table.rs @@ -196,6 +196,14 @@ impl Table { } } +impl std::cmp::PartialEq for Table { + fn eq(&self, other: &Self) -> bool { + self.handle == other.handle + } +} + +impl std::cmp::Eq for Table {} + impl<'a> Exportable<'a> for Table { fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> { match _extern { diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 899a5d118d7..3bd251b1430 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -99,6 +99,14 @@ pub unsafe extern "C" fn wasm_global_set(global: &mut wasm_global_t, val: &wasm_ } } +#[no_mangle] +pub unsafe extern "C" fn wasm_global_same( + wasm_global1: &wasm_global_t, + wasm_global2: &wasm_global_t, +) -> bool { + wasm_global1.inner == wasm_global2.inner +} + #[no_mangle] pub extern "C" fn wasm_global_type( global: Option<&wasm_global_t>, diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index e546f67f7a6..6252b438751 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -53,6 +53,14 @@ pub unsafe extern "C" fn wasm_memory_copy(memory: &wasm_memory_t) -> Box bool { + wasm_memory1.inner == wasm_memory2.inner +} + #[no_mangle] pub unsafe extern "C" fn wasm_memory_type( memory: Option<&wasm_memory_t>, diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index c45ee56b957..300b91ee1c4 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -53,6 +53,14 @@ pub unsafe extern "C" fn wasm_table_size(table: &wasm_table_t) -> usize { table.inner.size(&ctx.inner) as _ } +#[no_mangle] +pub unsafe extern "C" fn wasm_table_same( + wasm_table1: &wasm_table_t, + wasm_table2: &wasm_table_t, +) -> bool { + wasm_table1.inner == wasm_table2.inner +} + #[no_mangle] pub unsafe extern "C" fn wasm_table_grow( _table: &mut wasm_table_t, diff --git a/lib/vm/src/context.rs b/lib/vm/src/context.rs index 2093418af6c..1b8ca708ab7 100644 --- a/lib/vm/src/context.rs +++ b/lib/vm/src/context.rs @@ -123,6 +123,14 @@ impl fmt::Debug for ContextHandle { } } +impl PartialEq for ContextHandle { + fn eq(&self, other: &Self) -> bool { + self.id == other.id && self.internal == other.internal + } +} + +impl Eq for ContextHandle {} + impl ContextHandle { /// Moves the given object into a context and returns a handle to it. pub fn new(ctx: &mut ContextObjects, val: T) -> Self { From eed0327101c4e9d3ff87d5f54e043dcd81ec61b1 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 2 Jul 2022 01:48:51 +0300 Subject: [PATCH 21/24] Update c-api examples to Context API --- lib/c-api/examples/deprecated-header.c | 2 ++ lib/c-api/examples/early-exit.c | 4 ++- lib/c-api/examples/exports-function.c | 2 ++ lib/c-api/examples/exports-global.c | 2 ++ lib/c-api/examples/features.c | 2 ++ lib/c-api/examples/imports-exports.c | 4 ++- lib/c-api/examples/instance.c | 2 ++ lib/c-api/examples/memory.c | 2 ++ lib/c-api/examples/memory2.c | 2 ++ lib/c-api/examples/wasi.c | 36 ++++++++++--------- lib/c-api/src/wasm_c_api/context.rs | 35 +++++++++++++++++- .../src/wasm_c_api/externals/function.rs | 21 +++++------ lib/c-api/src/wasm_c_api/instance.rs | 2 ++ lib/c-api/tests/wasm-c-api/example/callback.c | 24 ++++++------- lib/c-api/tests/wasm-c-api/example/finalize.c | 4 +++ lib/c-api/tests/wasm-c-api/example/global.c | 2 ++ lib/c-api/tests/wasm-c-api/example/hello.c | 4 ++- lib/c-api/tests/wasm-c-api/example/hostref.c | 4 ++- lib/c-api/tests/wasm-c-api/example/memory.c | 2 ++ lib/c-api/tests/wasm-c-api/example/multi.c | 4 ++- lib/c-api/tests/wasm-c-api/example/reflect.c | 2 ++ .../tests/wasm-c-api/example/serialize.c | 4 ++- lib/c-api/tests/wasm-c-api/example/start.c | 2 ++ lib/c-api/tests/wasm-c-api/example/table.c | 4 ++- lib/c-api/tests/wasm-c-api/example/threads.c | 7 +++- lib/c-api/tests/wasm-c-api/example/trap.c | 4 ++- lib/c-api/tests/wasm-c-api/include/wasm.h | 5 ++- 27 files changed, 132 insertions(+), 56 deletions(-) diff --git a/lib/c-api/examples/deprecated-header.c b/lib/c-api/examples/deprecated-header.c index ee425c7cc12..8e28bd78ef0 100644 --- a/lib/c-api/examples/deprecated-header.c +++ b/lib/c-api/examples/deprecated-header.c @@ -21,6 +21,8 @@ int main(int argc, const char *argv[]) { printf("Initializing...\n"); own wasm_engine_t* engine = wasm_engine_new(); own wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // ===================== wasm_limits_t limits1 = { diff --git a/lib/c-api/examples/early-exit.c b/lib/c-api/examples/early-exit.c index d2410ca8baf..5bff06f343b 100644 --- a/lib/c-api/examples/early-exit.c +++ b/lib/c-api/examples/early-exit.c @@ -29,7 +29,7 @@ void print_frame(wasm_frame_t* frame) { wasm_store_t *store = NULL; -own wasm_trap_t* early_exit(const wasm_val_vec_t* args, wasm_val_vec_t* results) { +own wasm_trap_t* early_exit(wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results) { own wasm_message_t trap_message; wasm_name_new_from_string_nt(&trap_message, "trapping from a host import"); own wasm_trap_t *trap = wasm_trap_new(store, &trap_message); @@ -42,6 +42,8 @@ int main(int argc, const char *argv[]) { printf("Initializing...\n"); wasm_engine_t *engine = wasm_engine_new(); store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/examples/exports-function.c b/lib/c-api/examples/exports-function.c index 8c644638870..e7feaf4cd8f 100644 --- a/lib/c-api/examples/exports-function.c +++ b/lib/c-api/examples/exports-function.c @@ -20,6 +20,8 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/exports-global.c b/lib/c-api/examples/exports-global.c index ff20dfdeff4..dbbac9e81d6 100644 --- a/lib/c-api/examples/exports-global.c +++ b/lib/c-api/examples/exports-global.c @@ -19,6 +19,8 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/features.c b/lib/c-api/examples/features.c index c42215d1eb1..6f472617267 100644 --- a/lib/c-api/examples/features.c +++ b/lib/c-api/examples/features.c @@ -26,6 +26,8 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/imports-exports.c b/lib/c-api/examples/imports-exports.c index e56a7232735..dca1efa57f8 100644 --- a/lib/c-api/examples/imports-exports.c +++ b/lib/c-api/examples/imports-exports.c @@ -1,7 +1,7 @@ #include #include "wasmer.h" -wasm_trap_t* host_func_callback(const wasm_val_vec_t* args, wasm_val_vec_t* results) { +wasm_trap_t* host_func_callback(wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results) { printf("Calling back...\n> "); wasm_val_t val = WASM_I32_VAL(42); @@ -31,6 +31,8 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/instance.c b/lib/c-api/examples/instance.c index 6eb867d4ce0..2c50efee73e 100644 --- a/lib/c-api/examples/instance.c +++ b/lib/c-api/examples/instance.c @@ -20,6 +20,8 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/memory.c b/lib/c-api/examples/memory.c index d33295147b6..cf6343ac6f5 100644 --- a/lib/c-api/examples/memory.c +++ b/lib/c-api/examples/memory.c @@ -28,6 +28,8 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/memory2.c b/lib/c-api/examples/memory2.c index 8c009bd1f94..c9c0af980d7 100644 --- a/lib/c-api/examples/memory2.c +++ b/lib/c-api/examples/memory2.c @@ -20,6 +20,8 @@ int main(int argc, const char *argv[]) { printf("Initializing...\n"); own wasm_engine_t* engine = wasm_engine_new(); own wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // ===================== wasm_limits_t limits1 = { diff --git a/lib/c-api/examples/wasi.c b/lib/c-api/examples/wasi.c index 941a769135e..932e605f888 100644 --- a/lib/c-api/examples/wasi.c +++ b/lib/c-api/examples/wasi.c @@ -28,6 +28,24 @@ int main(int argc, const char* argv[]) { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + printf("Setting up WASI...\n"); + wasi_config_t* config = wasi_config_new("example_program"); + // TODO: error checking + const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; + wasi_config_arg(config, "--eval"); + wasi_config_arg(config, js_string); + wasi_config_capture_stdout(config); + + wasi_env_t* wasi_env = wasi_env_new(config); + if (!wasi_env) { + printf("> Error building WASI env!\n"); + print_wasmer_error(); + return 1; + } + + wasm_context_t* ctx = wasm_context_new(store, wasi_env); + wasm_store_context_set(store, ctx); + // Load binary. printf("Loading binary...\n"); FILE* file = fopen("assets/qjs.wasm", "r"); @@ -55,26 +73,10 @@ int main(int argc, const char* argv[]) { } wasm_byte_vec_delete(&binary); - - printf("Setting up WASI...\n"); - wasi_config_t* config = wasi_config_new("example_program"); - // TODO: error checking - const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; - wasi_config_arg(config, "--eval"); - wasi_config_arg(config, js_string); - wasi_config_capture_stdout(config); - - wasi_env_t* wasi_env = wasi_env_new(config); - if (!wasi_env) { - printf("> Error building WASI env!\n"); - print_wasmer_error(); - return 1; - } - // Instantiate. printf("Instantiating module...\n"); wasm_extern_vec_t imports; - bool get_imports_result = wasi_get_imports(store, module, wasi_env, &imports); + bool get_imports_result = wasi_get_imports(store, module, &imports); if (!get_imports_result) { printf("> Error getting WASI imports!\n"); diff --git a/lib/c-api/src/wasm_c_api/context.rs b/lib/c-api/src/wasm_c_api/context.rs index fbd6997051d..cefc75076de 100644 --- a/lib/c-api/src/wasm_c_api/context.rs +++ b/lib/c-api/src/wasm_c_api/context.rs @@ -1,6 +1,6 @@ use crate::wasm_c_api::store::wasm_store_t; use libc::c_void; -use wasmer_api::Context; +use wasmer_api::{Context, ContextMut}; /// Opaque type representing a WebAssembly context. #[allow(non_camel_case_types)] @@ -38,3 +38,36 @@ pub unsafe extern "C" fn wasm_context_new( /// See the module's documentation. #[no_mangle] pub unsafe extern "C" fn wasm_context_delete(_context: Option>) {} + +/// Opaque type representing a mut ref of a WebAssembly context. +#[allow(non_camel_case_types)] +pub struct wasm_context_ref_mut_t<'a> { + pub(crate) inner: ContextMut<'a, *mut c_void>, +} + +/// Get the value of `wasm_context_ref_mut_t` data. +#[no_mangle] +pub unsafe extern "C" fn wasm_context_ref_mut_get(ctx: &wasm_context_ref_mut_t) -> *mut c_void { + *ctx.inner.data() +} + +/// Set the value of [`ContextMut`] data. +/// +#[no_mangle] +pub unsafe extern "C" fn wasm_context_ref_mut_set( + ctx: &mut wasm_context_ref_mut_t, + new_val: *mut c_void, +) { + *ctx.inner.data_mut() = new_val; +} + +/// Deletes a WebAssembly context. +/// +/// # Example +/// +/// See the module's documentation. +#[no_mangle] +pub unsafe extern "C" fn wasm_context_ref_mut_delete( + _context: Option<&mut wasm_context_ref_mut_t>, +) { +} diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index f5daa91acc9..ca580bad17f 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,4 +1,4 @@ -use super::super::context::wasm_context_t; +use super::super::context::{wasm_context_ref_mut_t, wasm_context_t}; use super::super::store::wasm_store_t; use super::super::trap::wasm_trap_t; use super::super::types::{wasm_functype_t, wasm_valkind_enum}; @@ -32,20 +32,11 @@ impl wasm_func_t { #[allow(non_camel_case_types)] pub type wasm_func_callback_t = unsafe extern "C" fn( + context: &mut wasm_context_ref_mut_t, args: &wasm_val_vec_t, results: &mut wasm_val_vec_t, ) -> Option>; -#[allow(non_camel_case_types)] -pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( - env: *mut c_void, - args: &wasm_val_vec_t, - results: &mut wasm_val_vec_t, -) -> Option>; - -#[allow(non_camel_case_types)] -pub type wasm_env_finalizer_t = unsafe extern "C" fn(*mut c_void); - #[no_mangle] pub unsafe extern "C" fn wasm_func_new( store: Option<&wasm_store_t>, @@ -62,7 +53,7 @@ pub unsafe extern "C" fn wasm_func_new( let func_sig = &function_type.inner().function_type; let num_rets = func_sig.results().len(); - let inner_callback = move |_ctx: wasmer_api::ContextMut<'_, *mut c_void>, + let inner_callback = move |ctx: wasmer_api::ContextMut<'_, *mut c_void>, args: &[Value]| -> Result, RuntimeError> { let processed_args: wasm_val_vec_t = args @@ -81,7 +72,11 @@ pub unsafe extern "C" fn wasm_func_new( ] .into(); - let trap = callback(&processed_args, &mut results); + let trap = callback( + &mut wasm_context_ref_mut_t { inner: ctx }, + &processed_args, + &mut results, + ); if let Some(trap) = trap { return Err(trap.inner); diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 7e1fa6ed831..9d363815b4d 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -224,9 +224,11 @@ mod tests { // The `sum` host function implementation. wasm_trap_t* sum_callback( + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* arguments, wasm_val_vec_t* results ) { + (void) ctx_mut; wasm_val_t sum = { .kind = WASM_I32, .of = { arguments->data[0].of.i32 + arguments->data[1].of.i32 }, diff --git a/lib/c-api/tests/wasm-c-api/example/callback.c b/lib/c-api/tests/wasm-c-api/example/callback.c index 64f3d49f499..977ca727a4f 100644 --- a/lib/c-api/tests/wasm-c-api/example/callback.c +++ b/lib/c-api/tests/wasm-c-api/example/callback.c @@ -7,8 +7,6 @@ #define own -wasm_store_t* global_store = NULL; - // Print a Wasm value void wasm_val_print(wasm_val_t val) { switch (val.kind) { @@ -37,7 +35,7 @@ void wasm_val_print(wasm_val_t val) { // A function to be called from Wasm code. own wasm_trap_t* print_callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); wasm_val_print(args->data[0]); @@ -50,9 +48,9 @@ own wasm_trap_t* print_callback( // A function closure. own wasm_trap_t* closure_callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { - int i = *(int*) wasm_store_data_get(global_store); + int i = *(int*) wasm_context_ref_mut_get(ctx_mut); printf("Calling back closure...\n"); printf("> %d\n", i); @@ -66,10 +64,10 @@ int main(int argc, const char* argv[]) { // Initialize. printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); - global_store = wasm_store_new(engine); + wasm_store_t* store = wasm_store_new(engine); int i = 42; - wasm_context_t* ctx = wasm_context_new(global_store, &i); - wasm_store_context_set(global_store, ctx); + wasm_context_t* ctx = wasm_context_new(store, &i); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); @@ -91,7 +89,7 @@ int main(int argc, const char* argv[]) { // Compile. printf("Compiling module...\n"); - own wasm_module_t* module = wasm_module_new(global_store, &binary); + own wasm_module_t* module = wasm_module_new(store, &binary); if (!module) { printf("> Error compiling module!\n"); return 1; @@ -102,10 +100,10 @@ int main(int argc, const char* argv[]) { // Create external print functions. printf("Creating callback...\n"); own wasm_functype_t* print_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()); - own wasm_func_t* print_func = wasm_func_new(global_store, print_type, print_callback); + own wasm_func_t* print_func = wasm_func_new(store, print_type, print_callback); own wasm_functype_t* closure_type = wasm_functype_new_0_1(wasm_valtype_new_i32()); - own wasm_func_t* closure_func = wasm_func_new(global_store, closure_type, closure_callback); + own wasm_func_t* closure_func = wasm_func_new(store, closure_type, closure_callback); wasm_functype_delete(print_type); wasm_functype_delete(closure_type); @@ -117,7 +115,7 @@ int main(int argc, const char* argv[]) { }; wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs); own wasm_instance_t* instance = - wasm_instance_new(global_store, module, &imports, NULL); + wasm_instance_new(store, module, &imports, NULL); if (!instance) { printf("> Error instantiating module!\n"); return 1; @@ -162,7 +160,7 @@ int main(int argc, const char* argv[]) { // Shut down. printf("Shutting down...\n"); - wasm_store_delete(global_store); + wasm_store_delete(store); wasm_engine_delete(engine); // All done. diff --git a/lib/c-api/tests/wasm-c-api/example/finalize.c b/lib/c-api/tests/wasm-c-api/example/finalize.c index 502fc60b2c7..6532c3a6bdb 100644 --- a/lib/c-api/tests/wasm-c-api/example/finalize.c +++ b/lib/c-api/tests/wasm-c-api/example/finalize.c @@ -74,6 +74,8 @@ int main(int argc, const char* argv[]) { printf("Live count %d\n", live_count); printf("Creating store 1...\n"); wasm_store_t* store1 = wasm_store_new(engine); + wasm_context_t* ctx1 = wasm_context_new(store1, 0); + wasm_store_context_set(store1, ctx1); printf("Running in store 1...\n"); run_in_store(store1); @@ -81,6 +83,8 @@ int main(int argc, const char* argv[]) { printf("Creating store 2...\n"); wasm_store_t* store2 = wasm_store_new(engine); + wasm_context_t* ctx2 = wasm_context_new(store2, 0); + wasm_store_context_set(store2, ctx2); printf("Running in store 2...\n"); run_in_store(store2); diff --git a/lib/c-api/tests/wasm-c-api/example/global.c b/lib/c-api/tests/wasm-c-api/example/global.c index 5bd403369c3..2187c5cdd63 100644 --- a/lib/c-api/tests/wasm-c-api/example/global.c +++ b/lib/c-api/tests/wasm-c-api/example/global.c @@ -52,6 +52,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/hello.c b/lib/c-api/tests/wasm-c-api/example/hello.c index 740f099699f..555cd0a16e1 100644 --- a/lib/c-api/tests/wasm-c-api/example/hello.c +++ b/lib/c-api/tests/wasm-c-api/example/hello.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* hello_callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); printf("> Hello World!\n"); @@ -22,6 +22,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.c b/lib/c-api/tests/wasm-c-api/example/hostref.c index 1e787ab1902..d392e2c9b9c 100644 --- a/lib/c-api/tests/wasm-c-api/example/hostref.c +++ b/lib/c-api/tests/wasm-c-api/example/hostref.c @@ -10,7 +10,7 @@ // A function to be called from Wasm code. own wasm_trap_t* callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); printf("> %p\n", @@ -127,6 +127,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/memory.c b/lib/c-api/tests/wasm-c-api/example/memory.c index edd4ebadd0b..9380a52ab4a 100644 --- a/lib/c-api/tests/wasm-c-api/example/memory.c +++ b/lib/c-api/tests/wasm-c-api/example/memory.c @@ -98,6 +98,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/multi.c b/lib/c-api/tests/wasm-c-api/example/multi.c index 4a31e7e4da5..517429d240b 100644 --- a/lib/c-api/tests/wasm-c-api/example/multi.c +++ b/lib/c-api/tests/wasm-c-api/example/multi.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", @@ -44,6 +44,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/reflect.c b/lib/c-api/tests/wasm-c-api/example/reflect.c index d4383185ff0..8dc80ef571a 100644 --- a/lib/c-api/tests/wasm-c-api/example/reflect.c +++ b/lib/c-api/tests/wasm-c-api/example/reflect.c @@ -87,6 +87,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/serialize.c b/lib/c-api/tests/wasm-c-api/example/serialize.c index 8ea1a379af6..2e28300e9d9 100644 --- a/lib/c-api/tests/wasm-c-api/example/serialize.c +++ b/lib/c-api/tests/wasm-c-api/example/serialize.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* hello_callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); printf("> Hello World!\n"); @@ -22,6 +22,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/start.c b/lib/c-api/tests/wasm-c-api/example/start.c index f60c03c6468..9f2e96f4acd 100644 --- a/lib/c-api/tests/wasm-c-api/example/start.c +++ b/lib/c-api/tests/wasm-c-api/example/start.c @@ -23,6 +23,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/table.c b/lib/c-api/tests/wasm-c-api/example/table.c index 5e91a34a45d..5aa5b96d929 100644 --- a/lib/c-api/tests/wasm-c-api/example/table.c +++ b/lib/c-api/tests/wasm-c-api/example/table.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* neg_callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); results->data[0].kind = WASM_I32; @@ -78,6 +78,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/threads.c b/lib/c-api/tests/wasm-c-api/example/threads.c index d70bd1ae55c..ec68abb8930 100644 --- a/lib/c-api/tests/wasm-c-api/example/threads.c +++ b/lib/c-api/tests/wasm-c-api/example/threads.c @@ -13,7 +13,7 @@ const int N_THREADS = 10; const int N_REPS = 3; // A function to be called from Wasm code. -own wasm_trap_t* callback(const wasm_val_vec_t* args, wasm_val_vec_t* results) { +own wasm_trap_t* callback(wasm_context_ref_mut_t* ctx, const wasm_val_vec_t* args, wasm_val_vec_t* results) { assert(args->data[0].kind == WASM_I32); printf("> Thread %d running\n", args->data[0].of.i32); return NULL; @@ -31,6 +31,8 @@ void* run(void* args_abs) { // Rereate store and module. own wasm_store_t* store = wasm_store_new(args->engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); own wasm_module_t* module = wasm_module_obtain(store, args->module); // Run the example N times. @@ -119,6 +121,9 @@ int main(int argc, const char *argv[]) { // Compile and share. own wasm_store_t* store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); + own wasm_module_t* module = wasm_module_new(store, &binary); if (!module) { printf("> Error compiling module!\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/trap.c b/lib/c-api/tests/wasm-c-api/example/trap.c index 7b13d673539..974100d9818 100644 --- a/lib/c-api/tests/wasm-c-api/example/trap.c +++ b/lib/c-api/tests/wasm-c-api/example/trap.c @@ -11,7 +11,7 @@ wasm_store_t* store = NULL; // A function to be called from Wasm code. own wasm_trap_t* fail_callback( - const wasm_val_vec_t* args, wasm_val_vec_t* results + wasm_context_ref_mut_t* ctx, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); own wasm_name_t message; @@ -37,6 +37,8 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); store = wasm_store_new(engine); + wasm_context_t* ctx = wasm_context_new(store, 0); + wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/include/wasm.h b/lib/c-api/tests/wasm-c-api/include/wasm.h index 6540804cd67..3c163d890f5 100644 --- a/lib/c-api/tests/wasm-c-api/include/wasm.h +++ b/lib/c-api/tests/wasm-c-api/include/wasm.h @@ -146,6 +146,7 @@ WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*); // Context WASM_DECLARE_OWN(context) +WASM_DECLARE_OWN(context_ref_mut) WASM_API_EXTERN own void wasm_store_context_set(own wasm_store_t*, own wasm_context_t*); WASM_API_EXTERN own void wasm_store_data_set(own wasm_store_t*, own void*); @@ -421,9 +422,7 @@ WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const WASM_DECLARE_REF(func) typedef own wasm_trap_t* (*wasm_func_callback_t)( - const wasm_val_vec_t* args, own wasm_val_vec_t* results); -typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)( - void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results); + wasm_context_ref_mut_t*, const wasm_val_vec_t* args, own wasm_val_vec_t* results); WASM_API_EXTERN own wasm_func_t* wasm_func_new( wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t); From b5ae6399cef3e289ce9d7e9d0ec00324a8327684 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Wed, 6 Jul 2022 16:55:12 +0200 Subject: [PATCH 22/24] update Migration guide --- docs/migration_to_3.0.0.md | 40 +++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/docs/migration_to_3.0.0.md b/docs/migration_to_3.0.0.md index 310c214dc11..3ed2175b898 100644 --- a/docs/migration_to_3.0.0.md +++ b/docs/migration_to_3.0.0.md @@ -19,7 +19,9 @@ and provide examples to make migrating to the new API as simple as possible. This version introduces the following changes to make the Wasmer API more ergonomic and safe: 1. `ImportsObject` and the traits `Resolver`, `NamedResolver`, etc have been removed and replaced with a single simple type `Imports`. This reduces the complexity of setting up an `Instance`. The helper macro `imports!` can still be used. -2. The `Engine`s API has been simplified, Instead of the `wasmer` user choosing and setting up an engine explicitly, everything now uses the universal engine. All functionalites of the `staticlib`,`dylib` Engines should be available unless explicitly stated as unsupported. +2. There is a new `Context` that goes along the `Store`. The `Context` will keep track of all memory and functions used, removing old tracking and Weak/Strong pointer difference. Every function and memory that is retreive is linked to a specific `Context`, and cannot be mixed with another `Context` +3. `WasmerEnv` and associated traits and macro have been removed. To use Environenment, a simple structure now need to be attached to the `Context`, and can be retreive from current `Context`. All functions now takes a mendatory first argument that is of type `ContextMut<_>`, with `_` being either nothing `()` or the Environement type needed. the function creation `XXX_with_env(...)` don't exist anymore, simply use `Function::new(...)` or `Function::native_new(...)` with the correct `ContextMut<_>` type. Because the `WasmerEnv` and all helpers don't exists anymore, you have to import memory yourself, there isn't any per instance initialisation automatically done anymore. It's especialy important for WasiEnv context. `Env` can be accessed from a `Context` using `Context::data()` or `Context::data_mut()`. +4. The `Engine`s API has been simplified, Instead of the `wasmer` user choosing and setting up an engine explicitly, everything now uses the universal engine. All functionalites of the `staticlib`,`dylib` Engines should be available unless explicitly stated as unsupported. ## How to use Wasmer 3.0.0 @@ -42,9 +44,27 @@ TODO ## Differences +### Creating a Context + +You need a Store to create a context. Simple context is created using: + +```rust +let ctx = Context::new(&store, ()); +``` + +For a Context with a custom Env, it will be similar: + +```rust +#[derive(Clone)] +struct Env { + counter: i32, +} +let ctx = Context::new(&store, Env{counter: 0}); +``` + ### Managing imports -Instantiating a Wasm module is similar to 2.x.x.: +Instantiating a Wasm module is similar to 2.x with just the need of a context as difference: ```rust let import_object: Imports = imports! { @@ -52,7 +72,7 @@ let import_object: Imports = imports! { "host_function" => host_function, }, }; -let instance = Instance::new(&module, &import_object).expect("Could not instantiate module."); +let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); ``` You can also build the `Imports` object manually: @@ -60,7 +80,18 @@ You can also build the `Imports` object manually: ```rust let mut import_object: Imports = Imports::new(); import_object.define("env", "host_function", host_function); -let instance = Instance::new(&module, &import_object).expect("Could not instantiate module."); +let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); +``` + +For WASI, don't forget to import memory to `WasiEnv` + +```rust +let mut wasi_env = WasiState::new("hello").finalize()?; +let mut ctx = Context::new(&store, wasi_env.clone()); +let import_object = wasi_env.import_object(&mut ctx.as_context_mut(), &module)?; +let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); +let memory = instance.exports.get_memory("memory")?; +ctx.data_mut().set_memory(memory.clone()); ``` #### `ChainableNamedResolver` is removed @@ -100,7 +131,6 @@ let instance = Instance::new(&module, &imports! {})?; In Wasmer 3.0, there's only the universal engine. The user can ignore the engine details when using the API: - ```rust let wasm_bytes = wat2wasm( "..".as_bytes(), From a419ccdf52f1d259e4bd8db59f64bf61ad6bbacd Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Fri, 8 Jul 2022 15:33:29 -0700 Subject: [PATCH 23/24] Move Webassembly objects to Store and remove Context Co-authored-by: ptitSeb Co-authored-by: Manos Pitsidianakis --- benches/static_and_dynamic_functions.rs | 12 +- docs/migration_to_3.0.0.md | 19 +- examples/compiler_cranelift.rs | 9 +- examples/compiler_llvm.rs | 9 +- examples/compiler_singlepass.rs | 9 +- examples/early_exit.rs | 17 +- examples/engine_cross_compilation.rs | 2 +- examples/engine_dylib.rs | 2 +- examples/engine_headless.rs | 12 +- examples/engine_universal.rs | 9 +- examples/errors.rs | 12 +- examples/exports_function.rs | 14 +- examples/exports_global.rs | 36 +- examples/exports_memory.rs | 22 +- examples/features.rs | 10 +- examples/hello_world.rs | 20 +- examples/imports_exports.rs | 22 +- examples/imports_function.rs | 37 +- examples/imports_function_env.rs | 25 +- examples/imports_global.rs | 44 +- examples/instance.rs | 16 +- examples/memory.rs | 43 +- examples/metering.rs | 30 +- examples/platform_ios_headless.rs | 2 +- examples/table.rs | 52 +- examples/tunables_limit_memory.rs | 12 +- examples/wasi.rs | 16 +- examples/wasi_pipes.rs | 15 +- fuzz/fuzz_targets/deterministic.rs | 2 +- fuzz/fuzz_targets/equivalence_universal.rs | 6 +- fuzz/fuzz_targets/metering.rs | 2 +- fuzz/fuzz_targets/universal_cranelift.rs | 2 +- fuzz/fuzz_targets/universal_llvm.rs | 2 +- fuzz/fuzz_targets/universal_singlepass.rs | 2 +- lib/api/Cargo.toml | 9 +- lib/api/README.md | 2 +- lib/api/src/js/context.rs | 449 --------- lib/api/src/js/error.rs | 8 +- lib/api/src/js/export.rs | 41 +- lib/api/src/js/exports.rs | 20 +- lib/api/src/js/externals/function.rs | 193 ++-- lib/api/src/js/externals/global.rs | 66 +- lib/api/src/js/externals/memory.rs | 67 +- lib/api/src/js/externals/mod.rs | 18 +- lib/api/src/js/externals/table.rs | 60 +- lib/api/src/js/function_env.rs | 153 ++++ lib/api/src/js/imports.rs | 18 +- lib/api/src/js/instance.rs | 30 +- lib/api/src/js/js_import_object.rs | 4 +- lib/api/src/js/mem_access.rs | 10 +- lib/api/src/js/mod.rs | 8 +- lib/api/src/js/module.rs | 68 +- lib/api/src/js/native.rs | 25 +- lib/api/src/js/native_type.rs | 44 +- lib/api/src/js/ptr.rs | 18 +- lib/api/src/js/store.rs | 392 +++++++- lib/api/src/js/types.rs | 8 +- lib/api/src/js/value.rs | 14 +- lib/api/src/lib.rs | 29 +- lib/api/src/sys/context.rs | 199 ---- lib/api/src/sys/exports.rs | 22 +- lib/api/src/sys/extern_ref.rs | 25 +- lib/api/src/sys/externals/function.rs | 359 ++++---- lib/api/src/sys/externals/global.rs | 110 +-- lib/api/src/sys/externals/memory.rs | 98 +- lib/api/src/sys/externals/mod.rs | 16 +- lib/api/src/sys/externals/table.rs | 60 +- lib/api/src/sys/function_env.rs | 120 +++ lib/api/src/sys/imports.rs | 101 +- lib/api/src/sys/instance.rs | 34 +- lib/api/src/sys/mem_access.rs | 6 +- lib/api/src/sys/mod.rs | 7 +- lib/api/src/sys/module.rs | 99 +- lib/api/src/sys/native.rs | 10 +- lib/api/src/sys/native_type.rs | 66 +- lib/api/src/sys/ptr.rs | 28 +- lib/api/src/sys/store.rs | 215 ++++- lib/api/src/sys/value.rs | 13 +- lib/api/tests/js_externals.rs | 313 ++++--- lib/api/tests/js_instance.rs | 236 ++--- lib/api/tests/js_module.rs | 11 +- lib/api/tests/sys_externals.rs | 529 +++++------ lib/api/tests/sys_instance.rs | 26 +- lib/api/tests/sys_module.rs | 56 +- lib/api/tests/sys_reference_types.rs | 89 +- lib/c-api/examples/deprecated-header.c | 2 - lib/c-api/examples/early-exit.c | 4 +- lib/c-api/examples/exports-function.c | 2 - lib/c-api/examples/exports-global.c | 2 - lib/c-api/examples/features.c | 2 - lib/c-api/examples/imports-exports.c | 4 +- lib/c-api/examples/instance.c | 2 - lib/c-api/examples/memory.c | 2 - lib/c-api/examples/memory2.c | 2 - lib/c-api/examples/wasi.c | 40 +- lib/c-api/src/wasm_c_api/context.rs | 73 -- .../src/wasm_c_api/externals/function.rs | 196 ++-- lib/c-api/src/wasm_c_api/externals/global.rs | 90 +- lib/c-api/src/wasm_c_api/externals/memory.rs | 94 +- lib/c-api/src/wasm_c_api/externals/mod.rs | 276 +----- lib/c-api/src/wasm_c_api/externals/table.rs | 31 +- lib/c-api/src/wasm_c_api/function_env.rs | 63 ++ lib/c-api/src/wasm_c_api/instance.rs | 44 +- lib/c-api/src/wasm_c_api/macros.rs | 10 + lib/c-api/src/wasm_c_api/mod.rs | 4 +- lib/c-api/src/wasm_c_api/module.rs | 43 +- lib/c-api/src/wasm_c_api/store.rs | 88 +- lib/c-api/src/wasm_c_api/types/extern_.rs | 2 +- .../unstable/middlewares/metering.rs | 39 +- lib/c-api/src/wasm_c_api/unstable/module.rs | 6 +- lib/c-api/src/wasm_c_api/unstable/wasi.rs | 35 +- lib/c-api/src/wasm_c_api/value.rs | 13 +- lib/c-api/src/wasm_c_api/wasi/mod.rs | 85 +- lib/c-api/tests/wasm-c-api/example/callback.c | 12 +- .../tests/wasm-c-api/example/callback.cc | 32 +- lib/c-api/tests/wasm-c-api/example/finalize.c | 8 +- lib/c-api/tests/wasm-c-api/example/global.c | 2 - lib/c-api/tests/wasm-c-api/example/global.cc | 44 +- lib/c-api/tests/wasm-c-api/example/hello.c | 11 +- lib/c-api/tests/wasm-c-api/example/hello.cc | 7 + lib/c-api/tests/wasm-c-api/example/hostref.c | 4 +- lib/c-api/tests/wasm-c-api/example/hostref.cc | 32 +- lib/c-api/tests/wasm-c-api/example/memory.c | 2 - lib/c-api/tests/wasm-c-api/example/memory.cc | 12 +- lib/c-api/tests/wasm-c-api/example/multi.c | 4 +- lib/c-api/tests/wasm-c-api/example/multi.cc | 18 +- lib/c-api/tests/wasm-c-api/example/reflect.c | 2 - .../tests/wasm-c-api/example/serialize.c | 4 +- lib/c-api/tests/wasm-c-api/example/start.c | 2 - lib/c-api/tests/wasm-c-api/example/table.c | 4 +- lib/c-api/tests/wasm-c-api/example/table.cc | 44 +- lib/c-api/tests/wasm-c-api/example/threads.c | 7 +- lib/c-api/tests/wasm-c-api/example/threads.cc | 14 +- lib/c-api/tests/wasm-c-api/example/trap.c | 17 +- lib/c-api/tests/wasm-c-api/include/wasm.h | 16 +- lib/cli/src/commands/run.rs | 54 +- lib/cli/src/commands/run/wasi.rs | 18 +- lib/cli/src/commands/wast.rs | 4 +- lib/compiler-cranelift/README.md | 2 +- .../src/translator/func_environ.rs | 6 +- lib/compiler-llvm/README.md | 2 +- .../src/translator/intrinsics.rs | 2 +- lib/compiler-singlepass/README.md | 2 +- lib/compiler/src/engine/artifact.rs | 6 +- lib/compiler/src/engine/resolver.rs | 6 +- lib/compiler/src/engine/tunables.rs | 20 +- lib/emscripten/src/bitwise.rs | 4 +- lib/emscripten/src/emscripten_target.rs | 154 ++-- lib/emscripten/src/env/mod.rs | 49 +- lib/emscripten/src/env/unix/mod.rs | 52 +- lib/emscripten/src/env/windows/mod.rs | 32 +- lib/emscripten/src/errno.rs | 4 +- lib/emscripten/src/exception.rs | 24 +- lib/emscripten/src/exec.rs | 8 +- lib/emscripten/src/exit.rs | 4 +- lib/emscripten/src/inet.rs | 4 +- lib/emscripten/src/io/mod.rs | 14 +- lib/emscripten/src/io/unix.rs | 24 +- lib/emscripten/src/io/windows.rs | 10 +- lib/emscripten/src/jmp.rs | 10 +- lib/emscripten/src/lib.rs | 861 +++++++++--------- lib/emscripten/src/libc.rs | 30 +- lib/emscripten/src/linking.rs | 10 +- lib/emscripten/src/lock.rs | 10 +- lib/emscripten/src/math.rs | 44 +- lib/emscripten/src/memory.rs | 34 +- lib/emscripten/src/process.rs | 72 +- lib/emscripten/src/pthread.rs | 76 +- lib/emscripten/src/signal.rs | 16 +- lib/emscripten/src/syscalls/mod.rs | 162 ++-- lib/emscripten/src/syscalls/unix.rs | 94 +- lib/emscripten/src/syscalls/windows.rs | 80 +- lib/emscripten/src/time.rs | 61 +- lib/emscripten/src/ucontext.rs | 10 +- lib/emscripten/src/unistd.rs | 4 +- lib/emscripten/src/utils.rs | 24 +- lib/emscripten/src/varargs.rs | 6 +- lib/middlewares/src/metering.rs | 74 +- lib/vm/src/export.rs | 10 +- lib/vm/src/extern_ref.rs | 6 +- lib/vm/src/function_env.rs | 27 + lib/vm/src/global.rs | 2 +- lib/vm/src/instance/mod.rs | 44 +- lib/vm/src/lib.rs | 12 +- lib/vm/src/memory.rs | 2 +- lib/vm/src/{context.rs => store.rs} | 96 +- lib/vm/src/table.rs | 2 +- lib/vm/src/trap/traphandlers.rs | 28 +- lib/vm/src/vmcontext.rs | 26 +- lib/wasi/README.md | 2 +- lib/wasi/src/lib.rs | 764 ++++++++-------- lib/wasi/src/state/builder.rs | 10 +- lib/wasi/src/state/pipe.rs | 6 +- lib/wasi/src/state/socket.rs | 30 +- lib/wasi/src/syscalls/legacy/snapshot0.rs | 24 +- lib/wasi/src/syscalls/mod.rs | 237 ++--- lib/wasi/src/syscalls/wasi.rs | 92 +- lib/wasi/src/syscalls/wasix32.rs | 216 ++--- lib/wasi/src/syscalls/wasix64.rs | 216 ++--- lib/wasi/tests/stdio.rs | 61 +- tests/compilers/deterministic.rs | 4 +- tests/compilers/imports.rs | 206 +++-- tests/compilers/issues.rs | 62 +- tests/compilers/metering.rs | 33 +- tests/compilers/middlewares.rs | 57 +- tests/compilers/multi_value_imports.rs | 4 +- tests/compilers/native_functions.rs | 180 ++-- tests/compilers/serialize.rs | 14 +- tests/compilers/traps.rs | 124 +-- tests/compilers/wasi.rs | 4 +- tests/compilers/wast.rs | 7 +- tests/lib/wast/src/spectest.rs | 42 +- tests/lib/wast/src/wasi_wast.rs | 35 +- tests/lib/wast/src/wast.rs | 27 +- 214 files changed, 5817 insertions(+), 5776 deletions(-) delete mode 100644 lib/api/src/js/context.rs create mode 100644 lib/api/src/js/function_env.rs delete mode 100644 lib/api/src/sys/context.rs create mode 100644 lib/api/src/sys/function_env.rs delete mode 100644 lib/c-api/src/wasm_c_api/context.rs create mode 100644 lib/c-api/src/wasm_c_api/function_env.rs create mode 100644 lib/vm/src/function_env.rs rename lib/vm/src/{context.rs => store.rs} (69%) diff --git a/benches/static_and_dynamic_functions.rs b/benches/static_and_dynamic_functions.rs index bc61ab3c4e8..7199c68da38 100644 --- a/benches/static_and_dynamic_functions.rs +++ b/benches/static_and_dynamic_functions.rs @@ -149,14 +149,14 @@ pub fn run_basic_dynamic_function(store: &Store, compiler_name: &str, c: &mut Cr fn run_static_benchmarks(_c: &mut Criterion) { #[cfg(feature = "llvm")] { - let store = + let mut store = Store::new_with_engine(&Universal::new(wasmer_compiler_llvm::LLVM::new()).engine()); run_basic_static_function(&store, "llvm", c); } #[cfg(feature = "cranelift")] { - let store = Store::new_with_engine( + let mut store = Store::new_with_engine( &Universal::new(wasmer_compiler_cranelift::Cranelift::new()).engine(), ); run_basic_static_function(&store, "cranelift", c); @@ -164,7 +164,7 @@ fn run_static_benchmarks(_c: &mut Criterion) { #[cfg(feature = "singlepass")] { - let store = Store::new_with_engine( + let mut store = Store::new_with_engine( &Universal::new(wasmer_compiler_singlepass::Singlepass::new()).engine(), ); run_basic_static_function(&store, "singlepass", c); @@ -174,14 +174,14 @@ fn run_static_benchmarks(_c: &mut Criterion) { fn run_dynamic_benchmarks(_c: &mut Criterion) { #[cfg(feature = "llvm")] { - let store = + let mut store = Store::new_with_engine(&Universal::new(wasmer_compiler_llvm::LLVM::new()).engine()); run_basic_dynamic_function(&store, "llvm", c); } #[cfg(feature = "cranelift")] { - let store = Store::new_with_engine( + let mut store = Store::new_with_engine( &Universal::new(wasmer_compiler_cranelift::Cranelift::new()).engine(), ); run_basic_dynamic_function(&store, "cranelift", c); @@ -189,7 +189,7 @@ fn run_dynamic_benchmarks(_c: &mut Criterion) { #[cfg(feature = "singlepass")] { - let store = Store::new_with_engine( + let mut store = Store::new_with_engine( &Universal::new(wasmer_compiler_singlepass::Singlepass::new()).engine(), ); run_basic_dynamic_function(&store, "singlepass", c); diff --git a/docs/migration_to_3.0.0.md b/docs/migration_to_3.0.0.md index 3ed2175b898..fc4f2511530 100644 --- a/docs/migration_to_3.0.0.md +++ b/docs/migration_to_3.0.0.md @@ -49,7 +49,7 @@ TODO You need a Store to create a context. Simple context is created using: ```rust -let ctx = Context::new(&store, ()); +let ctx = FunctionEnv::new(&mut store, ()); ``` For a Context with a custom Env, it will be similar: @@ -59,7 +59,7 @@ For a Context with a custom Env, it will be similar: struct Env { counter: i32, } -let ctx = Context::new(&store, Env{counter: 0}); +let ctx = FunctionEnv::new(&mut store, Env{counter: 0}); ``` ### Managing imports @@ -72,7 +72,7 @@ let import_object: Imports = imports! { "host_function" => host_function, }, }; -let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); +let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); ``` You can also build the `Imports` object manually: @@ -80,18 +80,17 @@ You can also build the `Imports` object manually: ```rust let mut import_object: Imports = Imports::new(); import_object.define("env", "host_function", host_function); -let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); +let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); ``` For WASI, don't forget to import memory to `WasiEnv` ```rust let mut wasi_env = WasiState::new("hello").finalize()?; -let mut ctx = Context::new(&store, wasi_env.clone()); -let import_object = wasi_env.import_object(&mut ctx.as_context_mut(), &module)?; -let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); +let import_object = wasi_env.import_object(&mut store, &module)?; +let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); let memory = instance.exports.get_memory("memory")?; -ctx.data_mut().set_memory(memory.clone()); +wasi_env.data_mut(&mut store).set_memory(memory.clone()); ``` #### `ChainableNamedResolver` is removed @@ -122,7 +121,7 @@ let wasm_bytes = wat2wasm( let compiler_config = Cranelift::default(); let engine = Universal::new(compiler_config).engine(); -let store = Store::new(&engine); +let mut store = Store::new(&engine); let module = Module::new(&store, wasm_bytes)?; let instance = Instance::new(&module, &imports! {})?; ``` @@ -137,7 +136,7 @@ let wasm_bytes = wat2wasm( )?; let compiler_config = Cranelift::default(); -let store = Store::new(&compiler_config); +let mut store = Store::new(&compiler_config); let module = Module::new(&store, wasm_bytes)?; let instance = Instance::new(&module, &imports! {})?; ``` diff --git a/examples/compiler_cranelift.rs b/examples/compiler_cranelift.rs index 8c6aff08dfa..9fce7497f03 100644 --- a/examples/compiler_cranelift.rs +++ b/examples/compiler_cranelift.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -33,8 +33,7 @@ fn main() -> Result<(), Box> { let compiler = Cranelift::default(); // Create the store - let store = Store::new_with_engine(&Universal::new(compiler).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -45,14 +44,14 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; let sum = instance.exports.get_function("sum")?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut store, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/compiler_llvm.rs b/examples/compiler_llvm.rs index b762443c415..dc68f7e0a1b 100644 --- a/examples/compiler_llvm.rs +++ b/examples/compiler_llvm.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_llvm::LLVM; @@ -33,8 +33,7 @@ fn main() -> Result<(), Box> { let compiler = LLVM::default(); // Create the store - let store = Store::new_with_engine(&Universal::new(compiler).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -45,14 +44,14 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; let sum = instance.exports.get_function("sum")?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut store, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/compiler_singlepass.rs b/examples/compiler_singlepass.rs index 2b7f87bea99..d44d0331897 100644 --- a/examples/compiler_singlepass.rs +++ b/examples/compiler_singlepass.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_singlepass::Singlepass; @@ -33,8 +33,7 @@ fn main() -> Result<(), Box> { let compiler = Singlepass::default(); // Create the store - let store = Store::new_with_engine(&Universal::new(compiler).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -45,14 +44,14 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; let sum = instance.exports.get_function("sum")?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. - let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut store, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/early_exit.rs b/examples/early_exit.rs index 9e2181cfd9b..4bfbc6bad3e 100644 --- a/examples/early_exit.rs +++ b/examples/early_exit.rs @@ -17,7 +17,8 @@ use anyhow::bail; use std::fmt; use wasmer::{ - imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TypedFunction, + imports, wat2wasm, Function, FunctionEnv, FunctionEnvMut, Instance, Module, Store, + TypedFunction, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -57,15 +58,15 @@ fn main() -> anyhow::Result<()> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. let module = Module::new(&store, wasm_bytes)?; // We declare the host function that we'll use to terminate execution. - fn early_exit(_ctx: ContextMut<()>) -> Result<(), ExitCode> { + fn early_exit(_ctx: FunctionEnvMut<()>) -> Result<(), ExitCode> { // This is where it happens. Err(ExitCode(1)) } @@ -73,23 +74,23 @@ fn main() -> anyhow::Result<()> { // Create an import object. let import_object = imports! { "env" => { - "early_exit" => Function::new_native(&mut ctx, early_exit), + "early_exit" => Function::new_native(&mut store, &env, early_exit), } }; println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // // Get the `run` function which we'll use as our entrypoint. println!("Calling `run` function..."); let run_func: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function(&mut ctx, "run")?; + instance.exports.get_typed_function(&mut store, "run")?; // When we call a function it can either succeed or fail. We expect it to fail. - match run_func.call(&mut ctx, 1, 7) { + match run_func.call(&mut store, 1, 7) { Ok(result) => { bail!( "Expected early termination with `ExitCode`, found: {}", diff --git a/examples/engine_cross_compilation.rs b/examples/engine_cross_compilation.rs index 467cb3facd5..0aa5c97b04d 100644 --- a/examples/engine_cross_compilation.rs +++ b/examples/engine_cross_compilation.rs @@ -79,7 +79,7 @@ fn main() -> Result<(), Box> { .engine(); // Create a store, that holds the engine. - let store = Store::new_with_engine(&engine); + let mut store = Store::new_with_engine(&engine); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/engine_dylib.rs b/examples/engine_dylib.rs index 53be3ee62f2..2b9c4d7a773 100644 --- a/examples/engine_dylib.rs +++ b/examples/engine_dylib.rs @@ -55,7 +55,7 @@ fn main() -> Result<(), Box> { let engine = Dylib::new(compiler_config).engine(); // Create a store, that holds the engine. - let store = Store::new_with_engine(&engine); + let mut store = Store::new_with_engine(&engine); println!("Compiling module..."); // Here we go. diff --git a/examples/engine_headless.rs b/examples/engine_headless.rs index 4d84f0e38ae..16aabfb5b9b 100644 --- a/examples/engine_headless.rs +++ b/examples/engine_headless.rs @@ -47,7 +47,7 @@ use tempfile::NamedTempFile; use wasmer::imports; use wasmer::wat2wasm; -use wasmer::Context; +use wasmer::FunctionEnv; use wasmer::Instance; use wasmer::Module; use wasmer::Store; @@ -85,7 +85,7 @@ fn main() -> Result<(), Box> { let engine = Universal::new(compiler_config).engine(); // Create a store, that holds the engine. - let store = Store::new_with_engine(&engine); + let mut store = Store::new_with_engine(&engine); println!("Compiling module..."); // Let's compile the Wasm module. @@ -106,8 +106,8 @@ fn main() -> Result<(), Box> { println!("Creating headless Universal engine..."); // We create a headless Universal engine. let engine = Universal::headless().engine(); - let store = Store::new_with_engine(&engine); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&engine); + let mut env = FunctionEnv::new(&mut store, ()); println!("Deserializing module..."); // Here we go. @@ -127,12 +127,12 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; println!("Calling `sum` function..."); // The Wasm module exports a function called `sum`. let sum = instance.exports.get_function("sum")?; - let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut store, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/engine_universal.rs b/examples/engine_universal.rs index 819879669cb..1b6f2398b84 100644 --- a/examples/engine_universal.rs +++ b/examples/engine_universal.rs @@ -18,7 +18,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -52,8 +52,7 @@ fn main() -> Result<(), Box> { let engine = Universal::new(compiler_config).engine(); // Create a store, that holds the engine. - let store = Store::new_with_engine(&engine); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&engine); println!("Compiling module..."); // Here we go. @@ -73,12 +72,12 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // And here we go again. Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; println!("Calling `sum` function..."); // The Wasm module exports a function called `sum`. let sum = instance.exports.get_function("sum")?; - let results = sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])?; + let results = sum.call(&mut store, &[Value::I32(1), Value::I32(2)])?; println!("Results: {:?}", results); assert_eq!(results.to_vec(), vec![Value::I32(3)]); diff --git a/examples/errors.rs b/examples/errors.rs index cf701dd1fb7..d28698f8051 100644 --- a/examples/errors.rs +++ b/examples/errors.rs @@ -13,7 +13,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction}; +use wasmer::{imports, wat2wasm, FunctionEnv, Instance, Module, Store, TypedFunction}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -39,8 +39,8 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -51,7 +51,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // @@ -63,11 +63,11 @@ fn main() -> Result<(), Box> { let div_by_zero: TypedFunction<(), i32> = instance .exports .get_function("div_by_zero")? - .native(&mut ctx)?; + .native(&mut store)?; println!("Calling `div_by_zero` function..."); // Let's call the `div_by_zero` exported function. - let result = div_by_zero.call(&mut ctx); + let result = div_by_zero.call(&mut store); // When we call a function it can either succeed or fail. We expect it to fail. match result { diff --git a/examples/exports_function.rs b/examples/exports_function.rs index 4ab86beac7f..e703976a44c 100644 --- a/examples/exports_function.rs +++ b/examples/exports_function.rs @@ -17,7 +17,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction, Value}; +use wasmer::{imports, wat2wasm, FunctionEnv, Instance, Module, Store, TypedFunction, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -40,8 +40,8 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -52,7 +52,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // @@ -74,7 +74,7 @@ fn main() -> Result<(), Box> { // Let's call the `sum` exported function. The parameters are a // slice of `Value`s. The results are a boxed slice of `Value`s. let args = [Value::I32(1), Value::I32(2)]; - let result = sum.call(&mut ctx, &args)?; + let result = sum.call(&mut store, &args)?; println!("Results: {:?}", result); assert_eq!(result.to_vec(), vec![Value::I32(3)]); @@ -87,13 +87,13 @@ fn main() -> Result<(), Box> { // `Rets`, respectively for the parameters and the results. If // those values don't match the exported function signature, an // error will be raised. - let sum_native: TypedFunction<(i32, i32), i32> = sum.native(&mut ctx)?; + let sum_native: TypedFunction<(i32, i32), i32> = sum.native(&mut store)?; println!("Calling `sum` function (natively)..."); // Let's call the `sum` exported function. The parameters are // statically typed Rust values of type `i32` and `i32`. The // result, in this case particular case, in a unit of type `i32`. - let result = sum_native.call(&mut ctx, 3, 4)?; + let result = sum_native.call(&mut store, 3, 4)?; println!("Results: {:?}", result); assert_eq!(result, 7); diff --git a/examples/exports_global.rs b/examples/exports_global.rs index 19687fb3209..4b8f765573e 100644 --- a/examples/exports_global.rs +++ b/examples/exports_global.rs @@ -16,7 +16,7 @@ //! Ready? use wasmer::{ - imports, wat2wasm, Context, Instance, Module, Mutability, Store, Type, TypedFunction, Value, + imports, wat2wasm, FunctionEnv, Instance, Module, Mutability, Store, Type, TypedFunction, Value, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -40,8 +40,8 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -52,7 +52,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // @@ -73,8 +73,8 @@ fn main() -> Result<(), Box> { println!("Getting globals types information..."); // Let's get the globals types. The results are `GlobalType`s. - let one_type = one.ty(&mut ctx); - let some_type = some.ty(&mut ctx); + let one_type = one.ty(&store); + let some_type = some.ty(&store); println!("`one` type: {:?} {:?}", one_type.mutability, one_type.ty); assert_eq!(one_type.mutability, Mutability::Const); @@ -91,11 +91,13 @@ fn main() -> Result<(), Box> { // // We will use an exported function for the `one` global // and the Global API for `some`. - let get_one: TypedFunction<(), f32> = - instance.exports.get_function("get_one")?.native(&mut ctx)?; + let get_one: TypedFunction<(), f32> = instance + .exports + .get_function("get_one")? + .native(&mut store)?; - let one_value = get_one.call(&mut ctx)?; - let some_value = some.get(&mut ctx); + let one_value = get_one.call(&mut store)?; + let some_value = some.get(&mut store); println!("`one` value: {:?}", one_value); assert_eq!(one_value, 1.0); @@ -106,13 +108,13 @@ fn main() -> Result<(), Box> { println!("Setting global values..."); // Trying to set the value of a immutable global (`const`) // will result in a `RuntimeError`. - let result = one.set(&mut ctx, Value::F32(42.0)); + let result = one.set(&mut store, Value::F32(42.0)); assert_eq!( result.expect_err("Expected an error").message(), "Attempted to set an immutable global" ); - let one_result = one.get(&mut ctx); + let one_result = one.get(&mut store); println!("`one` value after `set`: {:?}", one_result); assert_eq!(one_result, Value::F32(1.0)); @@ -124,14 +126,14 @@ fn main() -> Result<(), Box> { let set_some: TypedFunction = instance .exports .get_function("set_some")? - .native(&mut ctx)?; - set_some.call(&mut ctx, 21.0)?; - let some_result = some.get(&mut ctx); + .native(&mut store)?; + set_some.call(&mut store, 21.0)?; + let some_result = some.get(&mut store); println!("`some` value after `set_some`: {:?}", some_result); assert_eq!(some_result, Value::F32(21.0)); - some.set(&mut ctx, Value::F32(42.0))?; - let some_result = some.get(&mut ctx); + some.set(&mut store, Value::F32(42.0))?; + let some_result = some.get(&mut store); println!("`some` value after `set`: {:?}", some_result); assert_eq!(some_result, Value::F32(42.0)); diff --git a/examples/exports_memory.rs b/examples/exports_memory.rs index f8f5b29feb7..9d0f74726da 100644 --- a/examples/exports_memory.rs +++ b/examples/exports_memory.rs @@ -11,7 +11,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction, WasmPtr}; +use wasmer::{imports, wat2wasm, FunctionEnv, Instance, Module, Store, TypedFunction, WasmPtr}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -37,8 +37,8 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -49,10 +49,10 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; let load: TypedFunction<(), (WasmPtr, i32)> = - instance.exports.get_typed_function(&mut ctx, "load")?; + instance.exports.get_typed_function(&mut store, "load")?; // Here we go. // @@ -64,15 +64,15 @@ fn main() -> Result<(), Box> { // // The first thing we might be intersted in is the size of the memory. // Let's get it! - println!("Memory size (pages) {:?}", memory.size(&mut ctx)); - println!("Memory size (bytes) {:?}", memory.data_size(&mut ctx)); + println!("Memory size (pages) {:?}", memory.size(&mut store)); + println!("Memory size (bytes) {:?}", memory.data_size(&mut store)); // Oh! Wait, before reading the contents, we need to know // where to find what we are looking for. // // Fortunately, the Wasm module exports a `load` function // which will tell us the offset and length of the string. - let (ptr, length) = load.call(&mut ctx)?; + let (ptr, length) = load.call(&mut store)?; println!("String offset: {:?}", ptr.offset()); println!("String length: {:?}", length); @@ -81,7 +81,7 @@ fn main() -> Result<(), Box> { // We will get bytes out of the memory so we need to // decode them into a string. let str = ptr - .read_utf8_string(&mut ctx, memory, length as u32) + .read_utf8_string(&mut store, memory, length as u32) .unwrap(); println!("Memory contents: {:?}", str); @@ -91,7 +91,7 @@ fn main() -> Result<(), Box> { // To do that, we'll make a slice from our pointer and change the content // of each element. let new_str = b"Hello, Wasmer!"; - let values = ptr.slice(&mut ctx, memory, new_str.len() as u32).unwrap(); + let values = ptr.slice(&mut store, memory, new_str.len() as u32).unwrap(); for i in 0..new_str.len() { values.index(i as u64).write(new_str[i]).unwrap(); } @@ -104,7 +104,7 @@ fn main() -> Result<(), Box> { println!("New string length: {:?}", new_str.len()); let str = ptr - .read_utf8_string(&mut ctx, memory, new_str.len() as u32) + .read_utf8_string(&mut store, memory, new_str.len() as u32) .unwrap(); println!("New memory contents: {:?}", str); diff --git a/examples/features.rs b/examples/features.rs index d4f8058ce60..292c5c2cebc 100644 --- a/examples/features.rs +++ b/examples/features.rs @@ -10,7 +10,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Features, Instance, Module, Store, Value}; +use wasmer::{imports, wat2wasm, Features, FunctionEnv, Instance, Module, Store, Value}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -39,17 +39,17 @@ fn main() -> anyhow::Result<()> { let engine = Universal::new(compiler).features(features); // Now, let's define the store, and compile the module. - let store = Store::new_with_engine(&engine.engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&engine.engine()); + let mut env = FunctionEnv::new(&mut store, ()); let module = Module::new(&store, wasm_bytes)?; // Finally, let's instantiate the module, and execute something // :-). let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; let swap = instance.exports.get_function("swap")?; - let results = swap.call(&mut ctx, &[Value::I32(1), Value::I64(2)])?; + let results = swap.call(&mut store, &[Value::I32(1), Value::I64(2)])?; assert_eq!(results.to_vec(), vec![Value::I64(2), Value::I32(1)]); diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 39ea01df73b..28887d618bc 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -7,7 +7,8 @@ //! ``` use wasmer::{ - imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TypedFunction, + imports, wat2wasm, Function, FunctionEnv, FunctionEnvMut, Instance, Module, Store, + TypedFunction, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -46,19 +47,19 @@ fn main() -> anyhow::Result<()> { // However for the purposes of showing what's happening, we create a compiler // (`Cranelift`) and pass it to an engine (`Universal`). We then pass the engine to // the store and are now ready to compile and run WebAssembly! - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); // We then use our store and Wasm bytes to compile a `Module`. // A `Module` is a compiled WebAssembly module that isn't ready to execute yet. let module = Module::new(&store, wasm_bytes)?; // Next we'll set up our `Module` so that we can execute it. First, create - // a `Context` in which to instantiate our `Module`. - let mut context = Context::new(&store, ()); + // a `FunctionEnv` in which to instantiate our `Module`. + let mut context = FunctionEnv::new(&mut store, ()); // We define a function to act as our "env" "say_hello" function imported in the // Wasm program above. - fn say_hello_world(_ctx: ContextMut<'_, ()>) { + fn say_hello_world(_ctx: FunctionEnvMut<'_, ()>) { println!("Hello, world!") } @@ -67,7 +68,7 @@ fn main() -> anyhow::Result<()> { // We use the default namespace "env". "env" => { // And call our function "say_hello". - "say_hello" => Function::new_native(&mut context, say_hello_world), + "say_hello" => Function::new_native(&mut store, &context, say_hello_world), } }; @@ -75,18 +76,17 @@ fn main() -> anyhow::Result<()> { // // An `Instance` is a compiled WebAssembly module that has been set up // and is ready to execute. - let instance = Instance::new(&mut context, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // We get the `TypedFunction` with no parameters and no results from the instance. // // Recall that the Wasm module exported a function named "run", this is getting // that exported function from the `Instance`. - let run_func: TypedFunction<(), ()> = - instance.exports.get_typed_function(&mut context, "run")?; + let run_func: TypedFunction<(), ()> = instance.exports.get_typed_function(&mut store, "run")?; // Finally, we call our exported Wasm function which will call our "say_hello" // function and return. - run_func.call(&mut context)?; + run_func.call(&mut store)?; Ok(()) } diff --git a/examples/imports_exports.rs b/examples/imports_exports.rs index fc07e22a1eb..eb154317e3d 100644 --- a/examples/imports_exports.rs +++ b/examples/imports_exports.rs @@ -16,8 +16,8 @@ //! Ready? use wasmer::{ - imports, wat2wasm, Context, Function, FunctionType, Global, Instance, Memory, Module, Store, - Table, Type, Value, + imports, wat2wasm, Function, FunctionEnv, FunctionType, Global, Instance, Memory, Module, + Store, Table, Type, Value, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -44,8 +44,8 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -60,12 +60,12 @@ fn main() -> Result<(), Box> { // covered in more detail in other examples. println!("Creating the imported function..."); let host_function_signature = FunctionType::new(vec![], vec![Type::I32]); - let host_function = Function::new(&mut ctx, &host_function_signature, |_ctx, _args| { + let host_function = Function::new(&mut store, &env, &host_function_signature, |_ctx, _args| { Ok(vec![Value::I32(42)]) }); println!("Creating the imported global..."); - let host_global = Global::new(&mut ctx, Value::I32(42)); + let host_global = Global::new(&mut store, Value::I32(42)); // Create an import object. // @@ -90,7 +90,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // @@ -103,19 +103,19 @@ fn main() -> Result<(), Box> { // Let's get them. println!("Getting the exported function..."); let function = instance.exports.get::("guest_function")?; - println!("Got exported function of type: {:?}", function.ty(&mut ctx)); + println!("Got exported function of type: {:?}", function.ty(&store)); println!("Getting the exported global..."); let global = instance.exports.get::("guest_global")?; - println!("Got exported global of type: {:?}", global.ty(&mut ctx)); + println!("Got exported global of type: {:?}", global.ty(&store)); println!("Getting the exported memory..."); let memory = instance.exports.get::("guest_memory")?; - println!("Got exported memory of type: {:?}", memory.ty(&mut ctx)); + println!("Got exported memory of type: {:?}", memory.ty(&store)); println!("Getting the exported table..."); let table = instance.exports.get::
("guest_table")?; - println!("Got exported table of type: {:?}", table.ty(&mut ctx)); + println!("Got exported table of type: {:?}", table.ty(&store)); Ok(()) } diff --git a/examples/imports_function.rs b/examples/imports_function.rs index ca1bdebf39d..0e08360e94d 100644 --- a/examples/imports_function.rs +++ b/examples/imports_function.rs @@ -18,8 +18,8 @@ //! Ready? use wasmer::{ - imports, wat2wasm, Context, ContextMut, Function, FunctionType, Instance, Module, Store, Type, - TypedFunction, Value, + imports, wat2wasm, Function, FunctionEnv, FunctionEnvMut, FunctionType, Instance, Module, + Store, Type, TypedFunction, Value, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -45,8 +45,10 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut ctx1 = FunctionEnv::new(&mut store, ()); + struct MyEnv; + let mut ctx2 = FunctionEnv::new(&mut store, MyEnv {}); println!("Compiling module..."); // Let's compile the Wasm module. @@ -54,17 +56,22 @@ fn main() -> Result<(), Box> { // Create the functions let multiply_dynamic_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let multiply_dynamic = Function::new(&mut ctx, &multiply_dynamic_signature, |_ctx, args| { - println!("Calling `multiply_dynamic`..."); + let multiply_dynamic = Function::new( + &mut store, + &ctx1, + &multiply_dynamic_signature, + |_ctx, args| { + println!("Calling `multiply_dynamic`..."); - let result = args[0].unwrap_i32() * 2; + let result = args[0].unwrap_i32() * 2; - println!("Result of `multiply_dynamic`: {:?}", result); + println!("Result of `multiply_dynamic`: {:?}", result); - Ok(vec![Value::I32(result)]) - }); + Ok(vec![Value::I32(result)]) + }, + ); - fn multiply(_ctx: ContextMut<()>, a: i32) -> i32 { + fn multiply(_ctx: FunctionEnvMut, a: i32) -> i32 { println!("Calling `multiply_native`..."); let result = a * 3; @@ -72,7 +79,7 @@ fn main() -> Result<(), Box> { result } - let multiply_native = Function::new_native(&mut ctx, multiply); + let multiply_native = Function::new_native(&mut store, &ctx2, multiply); // Create an import object. let import_object = imports! { @@ -84,18 +91,18 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // // The Wasm module exports a function called `sum`. Let's get it. let sum: TypedFunction<(i32, i32), i32> = - instance.exports.get_function("sum")?.native(&mut ctx)?; + instance.exports.get_function("sum")?.native(&mut store)?; println!("Calling `sum` function..."); // Let's call the `sum` exported function. It will call each // of the imported functions. - let result = sum.call(&mut ctx, 1, 2)?; + let result = sum.call(&mut store, 1, 2)?; println!("Results of `sum`: {:?}", result); assert_eq!(result, 8); diff --git a/examples/imports_function_env.rs b/examples/imports_function_env.rs index 9f0fcafda96..7eee4b02245 100644 --- a/examples/imports_function_env.rs +++ b/examples/imports_function_env.rs @@ -21,7 +21,8 @@ use std::sync::{Arc, Mutex}; use wasmer::{ - imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TypedFunction, + imports, wat2wasm, Function, FunctionEnv, FunctionEnvMut, Instance, Module, Store, + TypedFunction, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -51,7 +52,7 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -65,7 +66,7 @@ fn main() -> Result<(), Box> { let shared_counter: Arc> = Arc::new(Mutex::new(0)); // Once we have our counter we'll wrap it inside en `Env` which we'll pass - // to our imported functionsvia the Context. + // to our imported functionsvia the FunctionEnv. // // This struct may have been anything. The only constraint is it must be // possible to know the size of the `Env` at compile time (i.e it has to @@ -77,18 +78,18 @@ fn main() -> Result<(), Box> { } // Create the functions - fn get_counter(ctx: ContextMut) -> i32 { + fn get_counter(ctx: FunctionEnvMut) -> i32 { *ctx.data().counter.lock().unwrap() } - fn add_to_counter(mut ctx: ContextMut, add: i32) -> i32 { + fn add_to_counter(mut ctx: FunctionEnvMut, add: i32) -> i32 { let mut counter_ref = ctx.data_mut().counter.lock().unwrap(); *counter_ref += add; *counter_ref } - let mut ctx = Context::new( - &store, + let mut env = FunctionEnv::new( + &mut store, Env { counter: shared_counter.clone(), }, @@ -97,14 +98,14 @@ fn main() -> Result<(), Box> { // Create an import object. let import_object = imports! { "env" => { - "get_counter" => Function::new_native(&mut ctx, get_counter), - "add_to_counter" => Function::new_native(&mut ctx, add_to_counter), + "get_counter" => Function::new_native(&mut store, &env, get_counter), + "add_to_counter" => Function::new_native(&mut store, &env, add_to_counter), } }; println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // @@ -112,7 +113,7 @@ fn main() -> Result<(), Box> { let increment_counter_loop: TypedFunction = instance .exports .get_function("increment_counter_loop")? - .native(&mut ctx)?; + .native(&mut store)?; let counter_value: i32 = *shared_counter.lock().unwrap(); println!("Initial ounter value: {:?}", counter_value); @@ -121,7 +122,7 @@ fn main() -> Result<(), Box> { // Let's call the `increment_counter_loop` exported function. // // It will loop five times thus incrementing our counter five times. - let result = increment_counter_loop.call(&mut ctx, 5)?; + let result = increment_counter_loop.call(&mut store, 5)?; let counter_value: i32 = *shared_counter.lock().unwrap(); println!("New counter value (host): {:?}", counter_value); diff --git a/examples/imports_global.rs b/examples/imports_global.rs index 7e6eaaddb5f..87e9318b711 100644 --- a/examples/imports_global.rs +++ b/examples/imports_global.rs @@ -15,7 +15,9 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Global, Instance, Module, Store, TypedFunction, Value}; +use wasmer::{ + imports, wat2wasm, FunctionEnv, Global, Instance, Module, Store, TypedFunction, Value, +}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -38,16 +40,16 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. let module = Module::new(&store, wasm_bytes)?; // Create the globals - let some = Global::new(&mut ctx, Value::F32(1.0)); - let other = Global::new_mut(&mut ctx, Value::F32(2.0)); + let some = Global::new(&mut store, Value::F32(1.0)); + let other = Global::new_mut(&mut store, Value::F32(2.0)); // Create an import object. // We add the two required globals in the `env` namespace. @@ -60,7 +62,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Here we go. // @@ -69,34 +71,34 @@ fn main() -> Result<(), Box> { let get_some: TypedFunction<(), f32> = instance .exports .get_function("get_some")? - .native(&mut ctx)?; + .native(&mut store)?; let get_other: TypedFunction<(), f32> = instance .exports .get_function("get_other")? - .native(&mut ctx)?; + .native(&mut store)?; - let some_result = get_some.call(&mut ctx)?; - let other_result = get_other.call(&mut ctx)?; + let some_result = get_some.call(&mut store)?; + let other_result = get_other.call(&mut store)?; println!("some value (via `get_some`): {:?}", some_result); - println!("some value (via Global API): {:?}", some.get(&mut ctx)); + println!("some value (via Global API): {:?}", some.get(&mut store)); println!("other value (via `get_other`): {:?}", other_result); - println!("other value (via Global API): {:?}", other.get(&mut ctx)); + println!("other value (via Global API): {:?}", other.get(&mut store)); - assert_eq!(some_result, some.get(&mut ctx).f32().unwrap()); - assert_eq!(other_result, other.get(&mut ctx).f32().unwrap()); + assert_eq!(some_result, some.get(&mut store).f32().unwrap()); + assert_eq!(other_result, other.get(&mut store).f32().unwrap()); println!("Setting global values..."); // Trying to set the value of a immutable global (`const`) // will result in a `RuntimeError`. - let result = some.set(&mut ctx, Value::F32(42.0)); + let result = some.set(&mut store, Value::F32(42.0)); assert_eq!( result.expect_err("Expected an error").message(), "Attempted to set an immutable global" ); - other.set(&mut ctx, Value::F32(21.0))?; - let other_result = other.get(&mut ctx); + other.set(&mut store, Value::F32(21.0))?; + let other_result = other.get(&mut store); println!("other value after `set`: {:?}", other_result); assert_eq!(other_result, Value::F32(21.0)); @@ -106,11 +108,11 @@ fn main() -> Result<(), Box> { let set_other: TypedFunction = instance .exports .get_function("set_other")? - .native(&mut ctx)?; - set_other.call(&mut ctx, 42.0)?; + .native(&mut store)?; + set_other.call(&mut store, 42.0)?; - println!("other value (via Global API): {:?}", other.get(&mut ctx)); - assert_eq!(other.get(&mut ctx), Value::F32(42.0)); + println!("other value (via Global API): {:?}", other.get(&mut store)); + assert_eq!(other.get(&mut store), Value::F32(42.0)); Ok(()) } diff --git a/examples/instance.rs b/examples/instance.rs index 5e8a9de09ac..2e102ea65bd 100644 --- a/examples/instance.rs +++ b/examples/instance.rs @@ -14,7 +14,7 @@ //! //! Ready? -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction}; +use wasmer::{imports, wat2wasm, FunctionEnv, Instance, Module, Store, TypedFunction}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -39,8 +39,8 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -51,7 +51,7 @@ fn main() -> Result<(), Box> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // We now have an instance ready to be used. // @@ -61,11 +61,13 @@ fn main() -> Result<(), Box> { // Here we are retrieving the exported function. We won't go into details here // as the main focus of this example is to show how to create an instance out // of a Wasm module and have basic interactions with it. - let add_one: TypedFunction = - instance.exports.get_function("add_one")?.native(&mut ctx)?; + let add_one: TypedFunction = instance + .exports + .get_function("add_one")? + .native(&mut store)?; println!("Calling `add_one` function..."); - let result = add_one.call(&mut ctx, 1)?; + let result = add_one.call(&mut store, 1)?; println!("Results of `add_one`: {:?}", result); assert_eq!(result, 2); diff --git a/examples/memory.rs b/examples/memory.rs index 66fa88f8e77..1d2b6b7a82d 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -15,7 +15,9 @@ //! Ready? use std::mem; -use wasmer::{imports, wat2wasm, Bytes, Context, Instance, Module, Pages, Store, TypedFunction}; +use wasmer::{ + imports, wat2wasm, Bytes, FunctionEnv, Instance, Module, Pages, Store, TypedFunction, +}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -57,8 +59,8 @@ fn main() -> anyhow::Result<()> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -69,17 +71,18 @@ fn main() -> anyhow::Result<()> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // The module exports some utility functions, let's get them. // // These function will be used later in this example. - let mem_size: TypedFunction<(), i32> = - instance.exports.get_typed_function(&mut ctx, "mem_size")?; + let mem_size: TypedFunction<(), i32> = instance + .exports + .get_typed_function(&mut store, "mem_size")?; let get_at: TypedFunction = - instance.exports.get_typed_function(&mut ctx, "get_at")?; + instance.exports.get_typed_function(&mut store, "get_at")?; let set_at: TypedFunction<(i32, i32), ()> = - instance.exports.get_typed_function(&mut ctx, "set_at")?; + instance.exports.get_typed_function(&mut store, "set_at")?; let memory = instance.exports.get_memory("memory")?; // We now have an instance ready to be used. @@ -93,15 +96,15 @@ fn main() -> anyhow::Result<()> { // The size in bytes can be found either by querying its pages or by // querying the memory directly. println!("Querying memory size..."); - assert_eq!(memory.size(&mut ctx), Pages::from(1)); - assert_eq!(memory.size(&mut ctx).bytes(), Bytes::from(65536 as usize)); - assert_eq!(memory.data_size(&mut ctx), 65536); + assert_eq!(memory.size(&mut store), Pages::from(1)); + assert_eq!(memory.size(&mut store).bytes(), Bytes::from(65536 as usize)); + assert_eq!(memory.data_size(&mut store), 65536); // Sometimes, the guest module may also export a function to let you // query the memory. Here we have a `mem_size` function, let's try it: - let result = mem_size.call(&mut ctx)?; + let result = mem_size.call(&mut store)?; println!("Memory size: {:?}", result); - assert_eq!(Pages::from(result as u32), memory.size(&mut ctx)); + assert_eq!(Pages::from(result as u32), memory.size(&mut store)); // Now that we know the size of our memory, it's time to see how wa // can change this. @@ -110,9 +113,9 @@ fn main() -> anyhow::Result<()> { // see how we can do that: println!("Growing memory..."); // Here we are requesting two more pages for our memory. - memory.grow(&mut ctx, 2)?; - assert_eq!(memory.size(&mut ctx), Pages::from(3)); - assert_eq!(memory.data_size(&mut ctx), 65536 * 3); + memory.grow(&mut store, 2)?; + assert_eq!(memory.size(&mut store), Pages::from(3)); + assert_eq!(memory.data_size(&mut store), 65536 * 3); // Now that we know how to query and adjust the size of the memory, // let's see how wa can write to it or read from it. @@ -122,9 +125,9 @@ fn main() -> anyhow::Result<()> { // addresses to write and read a value. let mem_addr = 0x2220; let val = 0xFEFEFFE; - set_at.call(&mut ctx, mem_addr, val)?; + set_at.call(&mut store, mem_addr, val)?; - let result = get_at.call(&mut ctx, mem_addr)?; + let result = get_at.call(&mut store, mem_addr)?; println!("Value at {:#x?}: {:?}", mem_addr, result); assert_eq!(result, val); @@ -133,9 +136,9 @@ fn main() -> anyhow::Result<()> { let page_size = 0x1_0000; let mem_addr = (page_size * 2) - mem::size_of_val(&val) as i32; let val = 0xFEA09; - set_at.call(&mut ctx, mem_addr, val)?; + set_at.call(&mut store, mem_addr, val)?; - let result = get_at.call(&mut ctx, mem_addr)?; + let result = get_at.call(&mut store, mem_addr)?; println!("Value at {:#x?}: {:?}", mem_addr, result); assert_eq!(result, val); diff --git a/examples/metering.rs b/examples/metering.rs index 613e2cab446..8f16e7adeec 100644 --- a/examples/metering.rs +++ b/examples/metering.rs @@ -18,7 +18,7 @@ use anyhow::bail; use std::sync::Arc; use wasmer::wasmparser::Operator; use wasmer::CompilerConfig; -use wasmer::{imports, wat2wasm, Context, Instance, Module, Store, TypedFunction}; +use wasmer::{imports, wat2wasm, FunctionEnv, Instance, Module, Store, TypedFunction}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; use wasmer_middlewares::{ @@ -70,8 +70,8 @@ fn main() -> anyhow::Result<()> { // // We use our previously create compiler configuration // with the Universal engine. - let store = Store::new_with_engine(&Universal::new(compiler_config).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(compiler_config).engine()); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -82,17 +82,19 @@ fn main() -> anyhow::Result<()> { println!("Instantiating module..."); // Let's instantiate the Wasm module. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // We now have an instance ready to be used. // // Our module exports a single `add_one` function. We want to // measure the cost of executing this function. - let add_one: TypedFunction = - instance.exports.get_function("add_one")?.native(&mut ctx)?; + let add_one: TypedFunction = instance + .exports + .get_function("add_one")? + .native(&mut store)?; println!("Calling `add_one` function once..."); - add_one.call(&mut ctx, 1)?; + add_one.call(&mut store, 1)?; // As you can see here, after the first call we have 6 remaining points. // @@ -100,7 +102,7 @@ fn main() -> anyhow::Result<()> { // * `local.get $value` is a `Operator::LocalGet` which costs 1 point; // * `i32.const` is a `Operator::I32Const` which costs 1 point; // * `i32.add` is a `Operator::I32Add` which costs 2 points. - let remaining_points_after_first_call = get_remaining_points(&mut ctx, &instance); + let remaining_points_after_first_call = get_remaining_points(&mut store, &instance); assert_eq!( remaining_points_after_first_call, MeteringPoints::Remaining(6) @@ -112,11 +114,11 @@ fn main() -> anyhow::Result<()> { ); println!("Calling `add_one` function twice..."); - add_one.call(&mut ctx, 1)?; + add_one.call(&mut store, 1)?; // We spent 4 more points with the second call. // We have 2 remaining points. - let remaining_points_after_second_call = get_remaining_points(&mut ctx, &instance); + let remaining_points_after_second_call = get_remaining_points(&mut store, &instance); assert_eq!( remaining_points_after_second_call, MeteringPoints::Remaining(2) @@ -131,7 +133,7 @@ fn main() -> anyhow::Result<()> { // calling it a third time will fail: we already consume 8 // points, there are only two remaining. println!("Calling `add_one` function a third time..."); - match add_one.call(&mut ctx, 1) { + match add_one.call(&mut store, 1) { Ok(result) => { bail!( "Expected failure while calling `add_one`, found: {}", @@ -142,7 +144,7 @@ fn main() -> anyhow::Result<()> { println!("Calling `add_one` failed."); // Because the last needed more than the remaining points, we should have an error. - let remaining_points = get_remaining_points(&mut ctx, &instance); + let remaining_points = get_remaining_points(&mut store, &instance); match remaining_points { MeteringPoints::Remaining(..) => { @@ -156,9 +158,9 @@ fn main() -> anyhow::Result<()> { // Now let's see how we can set a new limit... println!("Set new remaining points to 10"); let new_limit = 10; - set_remaining_points(&mut ctx, &instance, new_limit); + set_remaining_points(&mut store, &instance, new_limit); - let remaining_points = get_remaining_points(&mut ctx, &instance); + let remaining_points = get_remaining_points(&mut store, &instance); assert_eq!(remaining_points, MeteringPoints::Remaining(new_limit)); println!("Remaining points: {:?}", remaining_points); diff --git a/examples/platform_ios_headless.rs b/examples/platform_ios_headless.rs index c7b67adfdd6..72ab854de77 100644 --- a/examples/platform_ios_headless.rs +++ b/examples/platform_ios_headless.rs @@ -53,7 +53,7 @@ fn main() -> Result<(), Box> { let engine = Dylib::new(compiler_config).target(target).engine(); // Create a store, that holds the engine. - let store = Store::new_with_engine(&engine); + let mut store = Store::new_with_engine(&engine); println!("Compiling module..."); // Let's compile the Wasm module. diff --git a/examples/table.rs b/examples/table.rs index 70e365a5069..2250ba1a194 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -1,12 +1,12 @@ use wasmer::{ - imports, wat2wasm, Context, ContextMut, Function, Instance, Module, Store, TableType, Type, - TypedFunction, Value, + imports, wat2wasm, Function, FunctionEnv, FunctionEnvMut, Instance, Module, Store, TableType, + Type, TypedFunction, Value, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; /// A function we'll call through a table. -fn host_callback(_ctx: ContextMut<()>, arg1: i32, arg2: i32) -> i32 { +fn host_callback(_ctx: FunctionEnvMut<()>, arg1: i32, arg2: i32) -> i32 { arg1 + arg2 } @@ -52,23 +52,23 @@ fn main() -> anyhow::Result<()> { )?; // We set up our store with an engine and a compiler. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut env = FunctionEnv::new(&mut store, ()); // Then compile our Wasm. let module = Module::new(&store, wasm_bytes)?; let import_object = imports! {}; // And instantiate it with no imports. - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // We get our function that calls (i32, i32) -> i32 functions via table. // The first argument is the table index and the next 2 are the 2 arguments // to be passed to the function found in the table. let call_via_table: TypedFunction<(i32, i32, i32), i32> = instance .exports - .get_typed_function(&mut ctx, "call_callback")?; + .get_typed_function(&mut store, "call_callback")?; // And then call it with table index 1 and arguments 2 and 7. - let result = call_via_table.call(&mut ctx, 1, 2, 7)?; + let result = call_via_table.call(&mut store, 1, 2, 7)?; // Because it's the default function, we expect it to double each number and // then sum it, giving us 18. assert_eq!(result, 18); @@ -76,9 +76,9 @@ fn main() -> anyhow::Result<()> { // We then get the table from the instance. let guest_table = instance.exports.get_table("__indirect_function_table")?; // And demonstrate that it has the properties that we set in the Wasm. - assert_eq!(guest_table.size(&mut ctx), 3); + assert_eq!(guest_table.size(&mut store), 3); assert_eq!( - guest_table.ty(&mut ctx), + guest_table.ty(&store), TableType { ty: Type::FuncRef, minimum: 3, @@ -89,30 +89,30 @@ fn main() -> anyhow::Result<()> { // == Setting elements in a table == // We first construct a `Function` over our host_callback. - let func = Function::new_native(&mut ctx, host_callback); + let func = Function::new_native(&mut store, &env, host_callback); // And set table index 1 of that table to the host_callback `Function`. - guest_table.set(&mut ctx, 1, func.into())?; + guest_table.set(&mut store, 1, func.into())?; // We then repeat the call from before but this time it will find the host function // that we put at table index 1. - let result = call_via_table.call(&mut ctx, 1, 2, 7)?; + let result = call_via_table.call(&mut store, 1, 2, 7)?; // And because our host function simply sums the numbers, we expect 9. assert_eq!(result, 9); // == Growing a table == // We again construct a `Function` over our host_callback. - let func = Function::new_native(&mut ctx, host_callback); + let func = Function::new_native(&mut store, &env, host_callback); // And grow the table by 3 elements, filling in our host_callback in all the // new elements of the table. - let previous_size = guest_table.grow(&mut ctx, 3, func.into())?; + let previous_size = guest_table.grow(&mut store, 3, func.into())?; assert_eq!(previous_size, 3); - assert_eq!(guest_table.size(&mut ctx), 6); + assert_eq!(guest_table.size(&mut store), 6); assert_eq!( - guest_table.ty(&mut ctx), + guest_table.ty(&store), TableType { ty: Type::FuncRef, minimum: 3, @@ -121,8 +121,8 @@ fn main() -> anyhow::Result<()> { ); // Now demonstrate that the function we grew the table with is actually in the table. for table_index in 3..6 { - if let Value::FuncRef(Some(f)) = guest_table.get(&mut ctx, table_index as _).unwrap() { - let result = f.call(&mut ctx, &[Value::I32(1), Value::I32(9)])?; + if let Value::FuncRef(Some(f)) = guest_table.get(&mut store, table_index as _).unwrap() { + let result = f.call(&mut store, &[Value::I32(1), Value::I32(9)])?; assert_eq!(result[0], Value::I32(10)); } else { panic!("expected to find funcref in table!"); @@ -130,26 +130,26 @@ fn main() -> anyhow::Result<()> { } // Call function at index 0 to show that it's still the same. - let result = call_via_table.call(&mut ctx, 0, 2, 7)?; + let result = call_via_table.call(&mut store, 0, 2, 7)?; assert_eq!(result, 18); // Now overwrite index 0 with our host_callback. - let func = Function::new_native(&mut ctx, host_callback); - guest_table.set(&mut ctx, 0, func.into())?; + let func = Function::new_native(&mut store, &env, host_callback); + guest_table.set(&mut store, 0, func.into())?; // And verify that it does what we expect. - let result = call_via_table.call(&mut ctx, 0, 2, 7)?; + let result = call_via_table.call(&mut store, 0, 2, 7)?; assert_eq!(result, 9); // Now demonstrate that the host and guest see the same table and that both // get the same result. for table_index in 3..6 { - if let Value::FuncRef(Some(f)) = guest_table.get(&mut ctx, table_index as _).unwrap() { - let result = f.call(&mut ctx, &[Value::I32(1), Value::I32(9)])?; + if let Value::FuncRef(Some(f)) = guest_table.get(&mut store, table_index as _).unwrap() { + let result = f.call(&mut store, &[Value::I32(1), Value::I32(9)])?; assert_eq!(result[0], Value::I32(10)); } else { panic!("expected to find funcref in table!"); } - let result = call_via_table.call(&mut ctx, table_index, 1, 9)?; + let result = call_via_table.call(&mut store, table_index, 1, 9)?; assert_eq!(result, 10); } diff --git a/examples/tunables_limit_memory.rs b/examples/tunables_limit_memory.rs index 9b4f4e1ebd7..10e7c25bd92 100644 --- a/examples/tunables_limit_memory.rs +++ b/examples/tunables_limit_memory.rs @@ -3,8 +3,8 @@ use std::ptr::NonNull; use wasmer::{ imports, vm::{self, MemoryError, MemoryStyle, TableStyle, VMMemoryDefinition, VMTableDefinition}, - wat2wasm, BaseTunables, Context, Instance, Memory, MemoryType, Module, Pages, Store, TableType, - Target, Tunables, + wat2wasm, BaseTunables, FunctionEnv, Instance, Memory, MemoryType, Module, Pages, Store, + TableType, Target, Tunables, }; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; @@ -145,8 +145,8 @@ fn main() -> Result<(), Box> { let tunables = LimitingTunables::new(base, Pages(24)); // Create a store, that holds the engine and our custom tunables - let store = Store::new_with_tunables(&engine, tunables); - let mut ctx = Context::new(&store, ()); + let mut store = Store::new_with_tunables(&engine, tunables); + let mut env = FunctionEnv::new(&mut store, ()); println!("Compiling module..."); let module = Module::new(&store, wasm_bytes)?; @@ -155,7 +155,7 @@ fn main() -> Result<(), Box> { let import_object = imports! {}; // Now at this point, our custom tunables are used - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; // Check what happened let mut memories: Vec = instance @@ -168,7 +168,7 @@ fn main() -> Result<(), Box> { let first_memory = memories.pop().unwrap(); println!("Memory of this instance: {:?}", first_memory); - assert_eq!(first_memory.ty(&mut ctx).maximum.unwrap(), Pages(24)); + assert_eq!(first_memory.ty(&store).maximum.unwrap(), Pages(24)); Ok(()) } diff --git a/examples/wasi.rs b/examples/wasi.rs index 2eb77075e55..0c47100c386 100644 --- a/examples/wasi.rs +++ b/examples/wasi.rs @@ -15,7 +15,7 @@ //! //! Ready? -use wasmer::{AsContextMut, Context, Instance, Module, Store}; +use wasmer::{FunctionEnv, Instance, Module, Store}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; use wasmer_wasi::WasiState; @@ -32,7 +32,7 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -43,25 +43,23 @@ fn main() -> Result<(), Box> { let mut wasi_env = WasiState::new("hello") // .args(&["world"]) // .env("KEY", "Value") - .finalize()?; - // And now the context,using the newly created WasiEnv - let mut ctx = Context::new(&store, wasi_env.clone()); + .finalize(&mut store)?; println!("Instantiating module with WASI imports..."); // Then, we get the import object related to our WASI // and attach it to the Wasm instance. - let import_object = wasi_env.import_object(&mut ctx.as_context_mut(), &module)?; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let import_object = wasi_env.import_object(&mut store, &module)?; + let instance = Instance::new(&mut store, &module, &import_object)?; println!("Attach WASI memory..."); // Attach the memory export let memory = instance.exports.get_memory("memory")?; - ctx.data_mut().set_memory(memory.clone()); + wasi_env.data_mut(&mut store).set_memory(memory.clone()); println!("Call WASI `_start` function..."); // And we just call the `_start` function! let start = instance.exports.get_function("_start")?; - start.call(&mut ctx, &[])?; + start.call(&mut store, &[])?; Ok(()) } diff --git a/examples/wasi_pipes.rs b/examples/wasi_pipes.rs index b5b8a750459..1c8a2536046 100644 --- a/examples/wasi_pipes.rs +++ b/examples/wasi_pipes.rs @@ -12,7 +12,7 @@ //! Ready? use std::io::{Read, Write}; -use wasmer::{AsContextMut, Context, Instance, Module, Store}; +use wasmer::{FunctionEnv, Instance, Module, Store}; use wasmer_compiler::Universal; use wasmer_compiler_cranelift::Cranelift; use wasmer_wasi::{Pipe, WasiState}; @@ -29,7 +29,7 @@ fn main() -> Result<(), Box> { // Note that we don't need to specify the engine/compiler if we want to use // the default provided by Wasmer. // You can use `Store::default()` for that. - let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); + let mut store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine()); println!("Compiling module..."); // Let's compile the Wasm module. @@ -42,19 +42,18 @@ fn main() -> Result<(), Box> { let mut wasi_env = WasiState::new("hello") .stdin(Box::new(input.clone())) .stdout(Box::new(output.clone())) - .finalize()?; - let mut ctx = Context::new(&store, wasi_env.clone()); + .finalize(&mut store)?; println!("Instantiating module with WASI imports..."); // Then, we get the import object related to our WASI // and attach it to the Wasm instance. - let import_object = wasi_env.import_object(&mut ctx.as_context_mut(), &module)?; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let import_object = wasi_env.import_object(&mut store, &module)?; + let instance = Instance::new(&mut store, &module, &import_object)?; println!("Attach WASI memory..."); // Attach the memory export let memory = instance.exports.get_memory("memory")?; - ctx.data_mut().set_memory(memory.clone()); + wasi_env.data_mut(&mut store).set_memory(memory.clone()); let msg = "racecar go zoom"; println!("Writing \"{}\" to the WASI stdin...", msg); @@ -64,7 +63,7 @@ fn main() -> Result<(), Box> { println!("Call WASI `_start` function..."); // And we just call the `_start` function! let start = instance.exports.get_function("_start")?; - start.call(&mut ctx, &[])?; + start.call(&mut store, &[])?; println!("Reading from the WASI stdout..."); diff --git a/fuzz/fuzz_targets/deterministic.rs b/fuzz/fuzz_targets/deterministic.rs index ef550804599..b56da4d9006 100644 --- a/fuzz/fuzz_targets/deterministic.rs +++ b/fuzz/fuzz_targets/deterministic.rs @@ -24,7 +24,7 @@ impl Config for NoImportsConfig { } fn compile_and_compare(name: &str, engine: impl Engine, wasm: &[u8]) { - let store = Store::new_with_engine(&engine); + let mut store = Store::new_with_engine(&engine); // compile for first time let module = Module::new(&store, wasm).unwrap(); diff --git a/fuzz/fuzz_targets/equivalence_universal.rs b/fuzz/fuzz_targets/equivalence_universal.rs index 414f78adab2..be4edd3e463 100644 --- a/fuzz/fuzz_targets/equivalence_universal.rs +++ b/fuzz/fuzz_targets/equivalence_universal.rs @@ -48,7 +48,7 @@ impl std::fmt::Debug for WasmSmithModule { #[cfg(feature = "singlepass")] fn maybe_instantiate_singlepass(wasm_bytes: &[u8]) -> Result> { let compiler = Singlepass::default(); - let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); let module = Module::new(&store, &wasm_bytes); let module = match module { Ok(m) => m, @@ -69,7 +69,7 @@ fn maybe_instantiate_cranelift(wasm_bytes: &[u8]) -> Result> { let mut compiler = Cranelift::default(); compiler.canonicalize_nans(true); compiler.enable_verifier(); - let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); let module = Module::new(&store, &wasm_bytes)?; let instance = Instance::new(&module, &imports! {})?; Ok(Some(instance)) @@ -80,7 +80,7 @@ fn maybe_instantiate_llvm(wasm_bytes: &[u8]) -> Result> { let mut compiler = LLVM::default(); compiler.canonicalize_nans(true); compiler.enable_verifier(); - let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); let module = Module::new(&store, &wasm_bytes)?; let instance = Instance::new(&module, &imports! {})?; Ok(Some(instance)) diff --git a/fuzz/fuzz_targets/metering.rs b/fuzz/fuzz_targets/metering.rs index 4f53c207cee..cb91ee01874 100644 --- a/fuzz/fuzz_targets/metering.rs +++ b/fuzz/fuzz_targets/metering.rs @@ -56,7 +56,7 @@ fuzz_target!(|module: WasmSmithModule| { compiler.enable_verifier(); let metering = Arc::new(Metering::new(10, cost)); compiler.push_middleware(metering); - let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); let module = Module::new(&store, &wasm_bytes).unwrap(); match Instance::new(&module, &imports! {}) { Ok(_) => {} diff --git a/fuzz/fuzz_targets/universal_cranelift.rs b/fuzz/fuzz_targets/universal_cranelift.rs index a3642f55ed8..05fd7a3bcbc 100644 --- a/fuzz/fuzz_targets/universal_cranelift.rs +++ b/fuzz/fuzz_targets/universal_cranelift.rs @@ -42,7 +42,7 @@ fuzz_target!(|module: WasmSmithModule| { let mut compiler = Cranelift::default(); compiler.canonicalize_nans(true); compiler.enable_verifier(); - let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); let module = Module::new(&store, &wasm_bytes).unwrap(); match Instance::new(&module, &imports! {}) { Ok(_) => {} diff --git a/fuzz/fuzz_targets/universal_llvm.rs b/fuzz/fuzz_targets/universal_llvm.rs index 6b7d5fd127b..67cdc028894 100644 --- a/fuzz/fuzz_targets/universal_llvm.rs +++ b/fuzz/fuzz_targets/universal_llvm.rs @@ -42,7 +42,7 @@ fuzz_target!(|module: WasmSmithModule| { let mut compiler = LLVM::default(); compiler.canonicalize_nans(true); compiler.enable_verifier(); - let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); let module = Module::new(&store, &wasm_bytes).unwrap(); match Instance::new(&module, &imports! {}) { Ok(_) => {} diff --git a/fuzz/fuzz_targets/universal_singlepass.rs b/fuzz/fuzz_targets/universal_singlepass.rs index fe39c9d889c..e815bd1d797 100644 --- a/fuzz/fuzz_targets/universal_singlepass.rs +++ b/fuzz/fuzz_targets/universal_singlepass.rs @@ -40,7 +40,7 @@ fuzz_target!(|module: WasmSmithModule| { } let compiler = Singlepass::default(); - let store = Store::new_with_engine(&Universal::new(compiler).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); let module = Module::new(&store, &wasm_bytes); let module = match module { Ok(m) => m, diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 2ff837c00f9..db2916ebe03 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -41,6 +41,10 @@ target-lexicon = { version = "0.12.2", default-features = false } wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=2.3.0", optional = true } wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "=2.3.0", optional = true } wasmer-compiler-llvm = { path = "../compiler-llvm", version = "=2.3.0", optional = true } + +wasm-bindgen = { version = "0.2.74", optional = true } +js-sys = { version = "0.3.51", optional = true } + # - Mandatory dependencies for `sys` on Windows. [target.'cfg(all(not(target_arch = "wasm32"), target_os = "windows"))'.dependencies] winapi = "0.3" @@ -79,6 +83,7 @@ maintenance = { status = "actively-developed" } [features] default = ["sys-default"] +# default = ["js-default"] std = [] core = ["hashbrown"] @@ -100,7 +105,7 @@ default-llvm = ["default-compiler", "llvm"] # - Engines. engine = ["sys"] universal = [ - "engine", + "engine", "wasmer-compiler/universal_engine" ] default-engine = [] default-universal = [ @@ -111,7 +116,7 @@ default-universal = [ jit = ["universal"] # Features for `js`. -js = [] +js = ["wasm-bindgen", "js-sys"] js-default = ["js", "std", "wasm-types-polyfill"] wasm-types-polyfill = ["js", "wasmparser"] diff --git a/lib/api/README.md b/lib/api/README.md index 07e476d9930..51b209344ad 100644 --- a/lib/api/README.md +++ b/lib/api/README.md @@ -25,7 +25,7 @@ fn main() -> anyhow::Result<()> { i32.add)) "#; - let store = Store::default(); + let mut store = Store::default(); let module = Module::new(&store, &module_wat)?; // The module doesn't import anything, so we create an empty import object. let import_object = imports! {}; diff --git a/lib/api/src/js/context.rs b/lib/api/src/js/context.rs deleted file mode 100644 index 9823abbe7cb..00000000000 --- a/lib/api/src/js/context.rs +++ /dev/null @@ -1,449 +0,0 @@ -#![allow(dead_code)] -use crate::Store; - -/// We require the context to have a fixed memory address for its lifetime since -/// various bits of the VM have raw pointers that point back to it. Hence we -/// wrap the actual context in a box. -pub(crate) struct ContextInner { - pub(crate) objects: ContextObjects, - pub(crate) store: Store, - pub(crate) data: T, -} - -/// A context containing a set of WebAssembly instances, along with host state. -/// -/// All WebAssembly instances must exist within a context. In the majority of -/// cases each instance will have its own context, but it is possible to have -/// multiple instances in a context when these instances need to interact with -/// each other, for example sharing a memory between instances or calling -/// functions in another instance. -/// -/// The lifetimes of run-time WebAssembly objects, notably [`Instance`], -/// [`Memory`], [`Global`], [`Table`] and [`Function`] is tied to a context: -/// the backing memory for these objects is only freed when the context is -/// freed. -/// -/// The `T` generic parameter allows arbitrary data to be attached to a context. -/// This data can be accessed using the [`Context::data`] and -/// [`Context::data_mut`] methods. Host functions defined using -/// [`Function::new`] and [`Function::new_native`] receive -/// a reference to the context when they are called. -pub struct Context { - pub(crate) inner: Box>, -} - -impl Context { - /// Creates a new context with the given host state. - // TODO: Eliminate the Store type and move its functionality into Engine. - pub fn new(store: &Store, data: T) -> Self { - Self { - inner: Box::new(ContextInner { - objects: Default::default(), - store: store.clone(), - data, - }), - } - } - - /// Returns a reference to the host state in this context. - pub fn data(&self) -> &T { - &self.inner.data - } - - /// Returns a mutable- reference to the host state in this context. - pub fn data_mut(&mut self) -> &mut T { - &mut self.inner.data - } - - /// Drops the context and returns the host state that was stored in it. - pub fn into_data(self) -> T { - self.inner.data - } - - /// Returns a reference to the `Store` of this context. - pub fn store(&self) -> &Store { - &self.inner.store - } -} - -/// A temporary handle to a [`Context`]. -pub struct ContextRef<'a, T: 'a> { - inner: &'a ContextInner, -} - -impl<'a, T> ContextRef<'a, T> { - /// Returns a reference to the host state in this context. - pub fn data(&self) -> &'a T { - &self.inner.data - } - - /// Returns a reference to the `Store` of this context. - pub fn store(&self) -> &Store { - &self.inner.store - } - - pub(crate) fn objects(&self) -> &'a ContextObjects { - &self.inner.objects - } -} - -/// A temporary handle to a [`Context`]. -pub struct ContextMut<'a, T: 'a> { - inner: &'a mut ContextInner, -} - -impl ContextMut<'_, T> { - /// Returns a reference to the host state in this context. - pub fn data(&self) -> &T { - &self.inner.data - } - - /// Returns a mutable- reference to the host state in this context. - pub fn data_mut(&mut self) -> &mut T { - &mut self.inner.data - } - - pub(crate) fn objects_mut(&mut self) -> &mut ContextObjects { - &mut self.inner.objects - } - - /// Returns a reference to the `Store` of this context. - pub fn store(&self) -> &Store { - &self.inner.store - } - - /// Returns the raw pointer of the context - pub(crate) fn as_raw(&self) -> *mut ContextInner { - self.inner as *const ContextInner as *mut ContextInner - } - - /// Constructs the context from the raw pointer - pub(crate) unsafe fn from_raw(raw: *mut ContextInner) -> Self { - Self { inner: &mut *raw } - } -} - -/// Helper trait for a value that is convertible to a [`ContextRef`]. -pub trait AsContextRef { - /// Host state associated with the [`Context`]. - type Data; - - /// Returns a `ContextRef` pointing to the underlying context. - fn as_context_ref(&self) -> ContextRef<'_, Self::Data>; -} - -/// Helper trait for a value that is convertible to a [`ContextMut`]. -pub trait AsContextMut: AsContextRef { - /// Returns a `ContextMut` pointing to the underlying context. - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data>; -} - -impl AsContextRef for Context { - type Data = T; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - ContextRef { inner: &self.inner } - } -} -impl AsContextMut for Context { - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { - ContextMut { - inner: &mut self.inner, - } - } -} -impl AsContextRef for ContextRef<'_, T> { - type Data = T; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - ContextRef { inner: self.inner } - } -} -impl AsContextRef for ContextMut<'_, T> { - type Data = T; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - ContextRef { inner: self.inner } - } -} -impl AsContextMut for ContextMut<'_, T> { - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { - ContextMut { inner: self.inner } - } -} -impl AsContextRef for &'_ T { - type Data = T::Data; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - T::as_context_ref(*self) - } -} -impl AsContextRef for &'_ mut T { - type Data = T::Data; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - T::as_context_ref(*self) - } -} -impl AsContextMut for &'_ mut T { - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { - T::as_context_mut(*self) - } -} - -pub use objects::*; -mod objects { - use crate::js::export::{VMFunction, VMGlobal, VMMemory, VMTable}; - use std::{ - cell::UnsafeCell, - fmt, - marker::PhantomData, - num::{NonZeroU64, NonZeroUsize}, - ptr::NonNull, - sync::atomic::{AtomicU64, Ordering}, - }; - - /// Unique ID to identify a context. - /// - /// Every handle to an object managed by a context also contains the ID of the - /// context. This is used to check that a handle is always used with the - /// correct context. - #[derive(Debug, Copy, Clone, Eq, PartialEq)] - pub struct ContextId(NonZeroU64); - - impl Default for ContextId { - // Allocates a unique ID for a new context. - fn default() -> Self { - // No overflow checking is needed here: overflowing this would take - // thousands of years. - static NEXT_ID: AtomicU64 = AtomicU64::new(1); - Self(NonZeroU64::new(NEXT_ID.fetch_add(1, Ordering::Relaxed)).unwrap()) - } - } - - /// Trait to represent an object managed by a context. This is implemented on - /// the VM types managed by the context. - pub trait ContextObject: Sized { - fn list(ctx: &ContextObjects) -> &Vec; - fn list_mut(ctx: &mut ContextObjects) -> &mut Vec; - } - - macro_rules! impl_context_object { - ($($field:ident => $ty:ty,)*) => { - $( - impl ContextObject for $ty { - fn list(ctx: &ContextObjects) -> &Vec { - &ctx.$field - } - fn list_mut(ctx: &mut ContextObjects) -> &mut Vec { - &mut ctx.$field - } - } - )* - }; -} - - impl_context_object! { - functions => VMFunction, - tables => VMTable, - globals => VMGlobal, - memories => VMMemory, - instances => js_sys::WebAssembly::Instance, - } - - /// Set of objects managed by a context. - #[derive(Default)] - pub struct ContextObjects { - id: ContextId, - memories: Vec, - tables: Vec, - globals: Vec, - functions: Vec, - instances: Vec, - } - - impl ContextObjects { - /// Returns the ID of this context. - pub fn id(&self) -> ContextId { - self.id - } - - /// Returns a pair of mutable references from two handles. - /// - /// Panics if both handles point to the same object. - pub fn get_2_mut( - &mut self, - a: InternalContextHandle, - b: InternalContextHandle, - ) -> (&mut T, &mut T) { - assert_ne!(a.index(), b.index()); - let list = T::list_mut(self); - if a.index() < b.index() { - let (low, high) = list.split_at_mut(b.index()); - (&mut low[a.index()], &mut high[0]) - } else { - let (low, high) = list.split_at_mut(a.index()); - (&mut high[0], &mut low[a.index()]) - } - } - } - - /// Handle to an object managed by a context. - /// - /// Internally this is just an integer index into a context. A reference to the - /// context must be passed in separately to access the actual object. - pub struct ContextHandle { - id: ContextId, - internal: InternalContextHandle, - } - - impl core::cmp::PartialEq for ContextHandle { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } - } - impl Clone for ContextHandle { - fn clone(&self) -> Self { - Self { - id: self.id, - internal: self.internal, - } - } - } - - impl fmt::Debug for ContextHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ContextHandle") - .field("id", &self.id) - .field("internal", &self.internal.index()) - .finish() - } - } - - impl ContextHandle { - /// Moves the given object into a context and returns a handle to it. - pub fn new(ctx: &mut ContextObjects, val: T) -> Self { - Self { - id: ctx.id, - internal: InternalContextHandle::new(ctx, val), - } - } - - /// Returns a reference to the object that this handle points to. - pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { - assert_eq!(self.id, ctx.id, "object used with the wrong context"); - self.internal.get(ctx) - } - - /// Returns a mutable reference to the object that this handle points to. - pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { - assert_eq!(self.id, ctx.id, "object used with the wrong context"); - self.internal.get_mut(ctx) - } - - /// Returns the internal handle contains within this handle. - pub fn internal_handle(&self) -> InternalContextHandle { - self.internal - } - - /// Returns the ID of the context associated with the handle. - pub fn context_id(&self) -> ContextId { - self.id - } - - /// Constructs a `ContextHandle` from a `ContextId` and an `InternalContextHandle`. - /// - /// # Safety - /// Handling `InternalContextHandle` values is unsafe because they do not track context ID. - pub unsafe fn from_internal(id: ContextId, internal: InternalContextHandle) -> Self { - Self { id, internal } - } - } - - /// Internal handle to an object owned by the current context. - /// - /// Unlike `ContextHandle` this does not track the context ID: it is only - /// intended to be used within objects already owned by a context. - #[repr(transparent)] - pub struct InternalContextHandle { - // Use a NonZero here to reduce the size of Option. - idx: NonZeroUsize, - marker: PhantomData T>, - } - - impl Clone for InternalContextHandle { - fn clone(&self) -> Self { - *self - } - } - impl Copy for InternalContextHandle {} - - impl fmt::Debug for InternalContextHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("InternalContextHandle") - .field("idx", &self.idx) - .finish() - } - } - impl PartialEq for InternalContextHandle { - fn eq(&self, other: &Self) -> bool { - self.idx == other.idx - } - } - impl Eq for InternalContextHandle {} - - impl InternalContextHandle { - /// Moves the given object into a context and returns a handle to it. - pub fn new(ctx: &mut ContextObjects, val: T) -> Self { - let list = T::list_mut(ctx); - let idx = NonZeroUsize::new(list.len() + 1).unwrap(); - list.push(val); - Self { - idx, - marker: PhantomData, - } - } - - /// Returns a reference to the object that this handle points to. - pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { - &T::list(ctx)[self.idx.get() - 1] - } - - /// Returns a mutable reference to the object that this handle points to. - pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { - &mut T::list_mut(ctx)[self.idx.get() - 1] - } - - pub(crate) fn index(&self) -> usize { - self.idx.get() - } - - pub(crate) fn from_index(idx: usize) -> Option { - NonZeroUsize::new(idx).map(|idx| Self { - idx, - marker: PhantomData, - }) - } - } - - /// Data used by the generated code is generally located inline within the - /// `VMContext` for items defined in an instance. Host-defined objects are - /// allocated separately and owned directly by the context. - pub enum MaybeInstanceOwned { - /// The data is owned here. - Host(Box>), - - /// The data is stored inline in the `VMContext` of an instance. - Instance(NonNull), - } - - impl MaybeInstanceOwned { - /// Returns underlying pointer to the VM data. - pub fn as_ptr(&self) -> NonNull { - match self { - MaybeInstanceOwned::Host(p) => unsafe { NonNull::new_unchecked(p.get()) }, - MaybeInstanceOwned::Instance(p) => *p, - } - } - } -} diff --git a/lib/api/src/js/error.rs b/lib/api/src/js/error.rs index 5a25c99d88e..f334b4a1cec 100644 --- a/lib/api/src/js/error.rs +++ b/lib/api/src/js/error.rs @@ -163,10 +163,10 @@ pub enum InstantiationError { #[cfg_attr(feature = "std", error(transparent))] Start(RuntimeError), - /// Import from a different [`Context`]. - /// This error occurs when an import from a different context is used. - #[cfg_attr(feature = "std", error("cannot mix imports from different contexts"))] - BadContext, + /// Import from a different [`Store`]. + /// This error occurs when an import from a different store is used. + #[cfg_attr(feature = "std", error("cannot mix imports from different stores"))] + DifferentStores, /// A generic error occured while invoking API functions #[cfg_attr(feature = "std", error(transparent))] diff --git a/lib/api/src/js/export.rs b/lib/api/src/js/export.rs index 41d72145d01..4899443ce4d 100644 --- a/lib/api/src/js/export.rs +++ b/lib/api/src/js/export.rs @@ -1,5 +1,5 @@ -use crate::js::context::{AsContextMut, AsContextRef, InternalContextHandle}; use crate::js::error::WasmError; +use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle}; use crate::js::wasm_bindgen_polyfill::Global; use js_sys::Function; use js_sys::WebAssembly::{Memory, Table}; @@ -85,36 +85,33 @@ impl fmt::Debug for VMFunction { #[derive(Debug, Clone)] pub enum Export { /// A function export value. - Function(InternalContextHandle), + Function(InternalStoreHandle), /// A table export value. - Table(InternalContextHandle), + Table(InternalStoreHandle), /// A memory export value. - Memory(InternalContextHandle), + Memory(InternalStoreHandle), /// A global export value. - Global(InternalContextHandle), + Global(InternalStoreHandle), } impl Export { /// Return the export as a `JSValue`. - pub fn as_jsvalue<'context>(&self, ctx: &'context impl AsContextRef) -> &'context JsValue { + pub fn as_jsvalue<'context>(&self, ctx: &'context impl AsStoreRef) -> &'context JsValue { match self { Self::Memory(js_wasm_memory) => js_wasm_memory - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .memory .as_ref(), - Self::Function(js_func) => js_func - .get(ctx.as_context_ref().objects()) - .function - .as_ref(), + Self::Function(js_func) => js_func.get(ctx.as_store_ref().objects()).function.as_ref(), Self::Table(js_wasm_table) => js_wasm_table - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .table .as_ref(), Self::Global(js_wasm_global) => js_wasm_global - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .global .as_ref(), } @@ -123,14 +120,14 @@ impl Export { /// Convert a `JsValue` into an `Export` within a given `Context`. pub fn from_js_value( val: JsValue, - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, extern_type: ExternType, ) -> Result { match extern_type { ExternType::Memory(memory_type) => { if val.is_instance_of::() { - Ok(Self::Memory(InternalContextHandle::new( - &mut ctx.as_context_mut().objects_mut(), + Ok(Self::Memory(InternalStoreHandle::new( + &mut ctx.objects_mut(), VMMemory::new(val.unchecked_into::(), memory_type), ))) } else { @@ -145,8 +142,8 @@ impl Export { } ExternType::Global(global_type) => { if val.is_instance_of::() { - Ok(Self::Global(InternalContextHandle::new( - &mut ctx.as_context_mut().objects_mut(), + Ok(Self::Global(InternalStoreHandle::new( + &mut ctx.objects_mut(), VMGlobal::new(val.unchecked_into::(), global_type), ))) } else { @@ -155,8 +152,8 @@ impl Export { } ExternType::Function(function_type) => { if val.is_instance_of::() { - Ok(Self::Function(InternalContextHandle::new( - &mut ctx.as_context_mut().objects_mut(), + Ok(Self::Function(InternalStoreHandle::new( + &mut ctx.objects_mut(), VMFunction::new(val.unchecked_into::(), function_type), ))) } else { @@ -165,8 +162,8 @@ impl Export { } ExternType::Table(table_type) => { if val.is_instance_of::
() { - Ok(Self::Table(InternalContextHandle::new( - &mut ctx.as_context_mut().objects_mut(), + Ok(Self::Table(InternalStoreHandle::new( + &mut ctx.objects_mut(), VMTable::new(val.unchecked_into::
(), table_type), ))) } else { diff --git a/lib/api/src/js/exports.rs b/lib/api/src/js/exports.rs index c25e947eb91..90b5116729b 100644 --- a/lib/api/src/js/exports.rs +++ b/lib/api/src/js/exports.rs @@ -1,6 +1,6 @@ -use crate::js::context::AsContextRef; use crate::js::externals::{Extern, Function, Global, Memory, Table}; use crate::js::native::TypedFunction; +use crate::js::store::AsStoreRef; use crate::js::WasmTypeList; use indexmap::IndexMap; use std::fmt; @@ -18,7 +18,7 @@ use thiserror::Error; /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError}; -/// # let store = Store::default(); +/// # let mut store = Store::default(); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (global $one (export "glob") f32 (f32.const 1))) @@ -35,7 +35,7 @@ use thiserror::Error; /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError}; -/// # let store = Store::default(); +/// # let mut store = Store::default(); /// # let wasm_bytes = wat2wasm("(module)".as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; @@ -141,7 +141,7 @@ impl Exports { /// Get an export as a `TypedFunction`. pub fn get_native_function( &self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, name: &str, ) -> Result, ExportError> where @@ -154,7 +154,7 @@ impl Exports { /// Get an export as a `TypedFunction`. pub fn get_typed_function( &self, - ctx: &impl AsContextRef, + store: &impl AsStoreRef, name: &str, ) -> Result, ExportError> where @@ -162,14 +162,14 @@ impl Exports { Rets: WasmTypeList, { self.get_function(name)? - .native(ctx) + .native(store) .map_err(|_| ExportError::IncompatibleType) } /// Hack to get this working with nativefunc too pub fn get_with_generics<'a, T, Args, Rets>( &'a self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, name: &str, ) -> Result where @@ -187,7 +187,7 @@ impl Exports { /// This is useful for passing data into Context data, for example. pub fn get_with_generics_weak<'a, T, Args, Rets>( &'a self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, name: &str, ) -> Result where @@ -334,7 +334,7 @@ pub trait Exportable<'a>: Sized { pub trait ExportableWithGenerics<'a, Args: WasmTypeList, Rets: WasmTypeList>: Sized { /// Get an export with the given generics. fn get_self_from_extern_with_generics( - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, _extern: &'a Extern, ) -> Result; } @@ -343,7 +343,7 @@ pub trait ExportableWithGenerics<'a, Args: WasmTypeList, Rets: WasmTypeList>: Si /// with empty `Args` and `Rets`. impl<'a, T: Exportable<'a> + Clone + 'static> ExportableWithGenerics<'a, (), ()> for T { fn get_self_from_extern_with_generics( - _ctx: &impl AsContextRef, + _ctx: &impl AsStoreRef, _extern: &'a Extern, ) -> Result { T::get_self_from_extern(_extern).map(|i| i.clone()) diff --git a/lib/api/src/js/externals/function.rs b/lib/api/src/js/externals/function.rs index 17d6cd56b7a..232f1ad1bb8 100644 --- a/lib/api/src/js/externals/function.rs +++ b/lib/api/src/js/externals/function.rs @@ -1,14 +1,13 @@ pub use self::inner::{FromToNativeWasmType, HostFunction, WasmTypeList}; -use crate::js::context::{ - AsContextMut, AsContextRef, ContextHandle, ContextMut, InternalContextHandle, -}; use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; +use crate::js::function_env::FunctionEnvMut; +use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreMut}; use crate::js::types::{param_from_js, AsJs}; /* ValFuncRef */ -use crate::js::FunctionType; use crate::js::RuntimeError; use crate::js::TypedFunction; use crate::js::Value; +use crate::js::{FunctionEnv, FunctionType}; use js_sys::{Array, Function as JSFunction}; use std::iter::FromIterator; use wasm_bindgen::prelude::*; @@ -58,7 +57,7 @@ fn results_to_js_array(values: &[Value]) -> Array { /// [Closures as host functions tracking issue](https://github.com/wasmerio/wasmer/issues/1840) #[derive(Clone, PartialEq)] pub struct Function { - pub(crate) handle: ContextHandle, + pub(crate) handle: StoreHandle, } impl Function { @@ -71,7 +70,7 @@ impl Function { /// /// ``` /// # use wasmer::{Function, FunctionType, Type, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]); /// @@ -85,7 +84,7 @@ impl Function { /// /// ``` /// # use wasmer::{Function, FunctionType, Type, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]); /// @@ -95,55 +94,63 @@ impl Function { /// }); /// ``` #[allow(clippy::cast_ptr_alignment)] - pub fn new(ctx: &mut impl AsContextMut, ty: FT, func: F) -> Self + pub fn new( + store: &mut impl AsStoreMut, + ctx: &FunctionEnv, + ty: FT, + func: F, + ) -> Self where FT: Into, - F: Fn(ContextMut<'_, T>, &[Value]) -> Result, RuntimeError> + F: Fn(FunctionEnvMut<'_, T>, &[Value]) -> Result, RuntimeError> + 'static + Send + Sync, { - let mut ctx = ctx.as_context_mut(); + let mut store = store.as_store_mut(); let function_type = ty.into(); let func_ty = function_type.clone(); - let raw_ctx = ctx.as_raw() as *mut u8; - + let raw_store = store.as_raw() as *mut u8; + let raw_ctx = ctx.clone(); let wrapped_func: JsValue = match function_type.results().len() { 0 => Closure::wrap(Box::new(move |args: &Array| { - let mut ctx: ContextMut = unsafe { ContextMut::from_raw(raw_ctx as _) }; + let mut store: StoreMut = unsafe { StoreMut::from_raw(raw_store as _) }; + let mut ctx: FunctionEnvMut = raw_ctx.clone().into_mut(&mut store); let wasm_arguments = function_type .params() .iter() .enumerate() .map(|(i, param)| param_from_js(param, &args.get(i as u32))) .collect::>(); - let _results = func(ctx.as_context_mut(), &wasm_arguments)?; + let _results = func(ctx, &wasm_arguments)?; Ok(()) }) as Box Result<(), JsValue>>) .into_js_value(), 1 => Closure::wrap(Box::new(move |args: &Array| { - let mut ctx: ContextMut = unsafe { ContextMut::from_raw(raw_ctx as _) }; + let mut store: StoreMut = unsafe { StoreMut::from_raw(raw_store as _) }; + let mut ctx: FunctionEnvMut = raw_ctx.clone().into_mut(&mut store); let wasm_arguments = function_type .params() .iter() .enumerate() .map(|(i, param)| param_from_js(param, &args.get(i as u32))) .collect::>(); - let results = func(ctx.as_context_mut(), &wasm_arguments)?; + let results = func(ctx, &wasm_arguments)?; return Ok(result_to_js(&results[0])); }) as Box Result>) .into_js_value(), _n => Closure::wrap(Box::new(move |args: &Array| { - let mut ctx: ContextMut = unsafe { ContextMut::from_raw(raw_ctx as _) }; + let mut store: StoreMut = unsafe { StoreMut::from_raw(raw_store as _) }; + let mut ctx: FunctionEnvMut = raw_ctx.clone().into_mut(&mut store); let wasm_arguments = function_type .params() .iter() .enumerate() .map(|(i, param)| param_from_js(param, &args.get(i as u32))) .collect::>(); - let results = func(ctx.as_context_mut(), &wasm_arguments)?; + let results = func(ctx, &wasm_arguments)?; return Ok(results_to_js_array(&results)); }) as Box Result>) @@ -154,7 +161,7 @@ impl Function { JSFunction::new_with_args("f", "return f(Array.prototype.slice.call(arguments, 1))"); let binded_func = dyn_func.bind1(&JsValue::UNDEFINED, &wrapped_func); let vm_function = VMFunction::new(binded_func, func_ty); - Self::from_vm_export(&mut ctx, vm_function) + Self::from_vm_export(&mut store, vm_function) } /// Creates a new host `Function` from a native function. @@ -166,7 +173,7 @@ impl Function { /// /// ``` /// # use wasmer::{Store, Function}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// fn sum(a: i32, b: i32) -> i32 { /// a + b @@ -174,13 +181,17 @@ impl Function { /// /// let f = Function::new_native(&store, sum); /// ``` - pub fn new_native(ctx: &mut impl AsContextMut, func: F) -> Self + pub fn new_native( + store: &mut impl AsStoreMut, + env: &FunctionEnv, + func: F, + ) -> Self where F: HostFunction, Args: WasmTypeList, Rets: WasmTypeList, { - let mut ctx = ctx.as_context_mut(); + let mut store = store.as_store_mut(); if std::mem::size_of::() != 0 { Self::closures_unsupported_panic(); } @@ -191,14 +202,15 @@ impl Function { let as_table = ft.unchecked_ref::(); let func = as_table.get(address).unwrap(); - let binded_func = func.bind1( + let binded_func = func.bind2( &JsValue::UNDEFINED, - &JsValue::from_f64(ctx.as_raw() as *mut u8 as usize as f64), + &JsValue::from_f64(store.as_raw() as *mut u8 as usize as f64), + &JsValue::from_f64(env.handle.internal_handle().index() as f64), ); let ty = function.ty(); let vm_function = VMFunction::new(binded_func, ty); Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), + handle: StoreHandle::new(store.objects_mut(), vm_function), } } @@ -208,7 +220,7 @@ impl Function { /// /// ``` /// # use wasmer::{Function, Store, Type}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// fn sum(a: i32, b: i32) -> i32 { /// a + b @@ -219,8 +231,8 @@ impl Function { /// assert_eq!(f.ty().params(), vec![Type::I32, Type::I32]); /// assert_eq!(f.ty().results(), vec![Type::I32]); /// ``` - pub fn ty<'context>(&self, ctx: &'context impl AsContextRef) -> &'context FunctionType { - &self.handle.get(ctx.as_context_ref().objects()).ty + pub fn ty<'context>(&self, ctx: &'context impl AsStoreRef) -> &'context FunctionType { + &self.handle.get(ctx.as_store_ref().objects()).ty } /// Returns the number of parameters that this function takes. @@ -228,18 +240,19 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{Function, Store, Type}; - /// # let store = Store::default(); + /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # - /// fn sum(a: i32, b: i32) -> i32 { + /// fn sum(_ctx: FunctionEnvMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&store, sum); + /// let f = Function::new_native(&store, &env, sum); /// - /// assert_eq!(f.param_arity(), 2); + /// assert_eq!(f.param_arity(&store), 2); /// ``` - pub fn param_arity(&self, ctx: &impl AsContextRef) -> usize { + pub fn param_arity(&self, ctx: &impl AsStoreRef) -> usize { self.ty(ctx).params().len() } @@ -248,18 +261,19 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{Function, Store, Type}; - /// # let store = Store::default(); + /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # - /// fn sum(a: i32, b: i32) -> i32 { + /// fn sum(_ctx: FunctionEnvMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&store, sum); + /// let f = Function::new_native(&store, &env, sum); /// - /// assert_eq!(f.result_arity(), 1); + /// assert_eq!(f.result_arity(&store), 1); /// ``` - pub fn result_arity(&self, ctx: &impl AsContextRef) -> usize { + pub fn result_arity(&self, ctx: &impl AsStoreRef) -> usize { self.ty(ctx).results().len() } @@ -275,7 +289,7 @@ impl Function { /// /// ``` /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -292,27 +306,27 @@ impl Function { /// /// assert_eq!(sum.call(&[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); /// ``` - pub fn call( + pub fn call( &self, - ctx: &mut impl AsContextMut, + store: &mut impl AsStoreMut, params: &[Value], ) -> Result, RuntimeError> { let arr = js_sys::Array::new_with_length(params.len() as u32); - // let raw_ctx = ctx.as_context_mut().as_raw() as *mut u8; - // let mut ctx = unsafe { ContextMut::from_raw(raw_ctx as *mut ContextInner<()>) }; + // let raw_ctx = ctx.as_raw() as *mut u8; + // let mut env = unsafe { FunctionEnvMut::from_raw(raw_ctx as *mut StoreInner<()>) }; for (i, param) in params.iter().enumerate() { - let js_value = param.as_jsvalue(&ctx.as_context_ref()); + let js_value = param.as_jsvalue(&store.as_store_ref()); arr.set(i as u32, js_value); } let result = js_sys::Reflect::apply( - &self.handle.get(ctx.as_context_ref().objects()).function, + &self.handle.get(store.as_store_ref().objects()).function, &wasm_bindgen::JsValue::NULL, &arr, )?; - let result_types = self.handle.get(ctx.as_context_ref().objects()).ty.results(); + let result_types = self.handle.get(store.as_store_ref().objects()).ty.results(); match result_types.len() { 0 => Ok(Box::new([])), 1 => { @@ -331,19 +345,19 @@ impl Function { } } - pub(crate) fn from_vm_export(ctx: &mut impl AsContextMut, vm_function: VMFunction) -> Self { + pub(crate) fn from_vm_export(ctx: &mut impl AsStoreMut, vm_function: VMFunction) -> Self { Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), + handle: StoreHandle::new(ctx.objects_mut(), vm_function), } } pub(crate) fn from_vm_extern( - ctx: &mut impl AsContextMut, - internal: InternalContextHandle, + ctx: &mut impl AsStoreMut, + internal: InternalStoreHandle, ) -> Self { Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(ctx.as_store_ref().objects().id(), internal) }, } } @@ -355,7 +369,7 @@ impl Function { /// /// ``` /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -371,7 +385,7 @@ impl Function { /// let sum = instance.exports.get_function("sum").unwrap(); /// let sum_native = sum.native::<(i32, i32), i32>().unwrap(); /// - /// assert_eq!(sum_native.call(1, 2).unwrap(), 3); + /// assert_eq!(sum_native.call(&mut store, 1, 2).unwrap(), 3); /// ``` /// /// # Errors @@ -381,7 +395,7 @@ impl Function { /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -397,7 +411,7 @@ impl Function { /// let sum = instance.exports.get_function("sum").unwrap(); /// /// // This results in an error: `RuntimeError` - /// let sum_native = sum.native::<(i64, i64), i32>().unwrap(); + /// let sum_native = sum.native::<(i64, i64), i32>(&mut store).unwrap(); /// ``` /// /// If the `Rets` generic parameter does not match the exported function @@ -405,7 +419,7 @@ impl Function { /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -421,17 +435,17 @@ impl Function { /// let sum = instance.exports.get_function("sum").unwrap(); /// /// // This results in an error: `RuntimeError` - /// let sum_native = sum.native::<(i32, i32), i64>().unwrap(); + /// let sum_native = sum.native::<(i32, i32), i64>(&mut store).unwrap(); /// ``` pub fn native( &self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, ) -> Result, RuntimeError> where Args: WasmTypeList, Rets: WasmTypeList, { - let vm_function = self.handle.get(ctx.as_context_ref().objects()); + let vm_function = self.handle.get(ctx.as_store_ref().objects()); // type check { @@ -470,8 +484,8 @@ impl Function { } /// Checks whether this `Function` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { + self.handle.store_id() == ctx.as_store_ref().objects().id() } } @@ -495,7 +509,9 @@ impl fmt::Debug for Function { mod inner { use super::RuntimeError; use super::VMFunctionBody; - use crate::js::context::{AsContextMut, ContextInner, ContextMut}; + use crate::js::function_env::{FunctionEnvMut, VMFunctionEnvironment}; + use crate::js::store::{AsStoreMut, InternalStoreHandle, StoreHandle, StoreInner, StoreMut}; + use crate::js::FunctionEnv; use crate::js::NativeWasmTypeInto; use std::array::TryFromSliceError; use std::convert::{Infallible, TryInto}; @@ -641,7 +657,7 @@ mod inner { /// Constructs `Self` based on an array of values. /// /// # Safety - unsafe fn from_array(ctx: &mut impl AsContextMut, array: Self::Array) -> Self; + unsafe fn from_array(ctx: &mut impl AsStoreMut, array: Self::Array) -> Self; /// Constructs `Self` based on a slice of values. /// @@ -652,7 +668,7 @@ mod inner { /// /// # Safety unsafe fn from_slice( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, slice: &[f64], ) -> Result; @@ -660,7 +676,7 @@ mod inner { /// (list) of values. /// /// # Safety - unsafe fn into_array(self, ctx: &mut impl AsContextMut) -> Self::Array; + unsafe fn into_array(self, ctx: &mut impl AsStoreMut) -> Self::Array; /// Allocates and return an empty array of type `Array` that /// will hold a tuple (list) of values, usually to hold the @@ -671,13 +687,13 @@ mod inner { /// `CStruct`. /// /// # Safety - unsafe fn from_c_struct(ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self; + unsafe fn from_c_struct(ctx: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self; /// Builds and returns a C struct of type `CStruct` from a /// tuple (list) of values. /// /// # Safety - unsafe fn into_c_struct(self, ctx: &mut impl AsContextMut) -> Self::CStruct; + unsafe fn into_c_struct(self, ctx: &mut impl AsStoreMut) -> Self::CStruct; /// Writes the contents of a C struct to an array of `f64`. /// @@ -863,7 +879,7 @@ mod inner { #[allow(unused_mut)] #[allow(clippy::unused_unit)] #[allow(clippy::missing_safety_doc)] - unsafe fn from_array(mut _ctx: &mut impl AsContextMut, array: Self::Array) -> Self { + unsafe fn from_array(mut _ctx: &mut impl AsStoreMut, array: Self::Array) -> Self { // Unpack items of the array. #[allow(non_snake_case)] let [ $( $x ),* ] = array; @@ -877,13 +893,13 @@ mod inner { } #[allow(clippy::missing_safety_doc)] - unsafe fn from_slice(ctx: &mut impl AsContextMut, slice: &[f64]) -> Result { + unsafe fn from_slice(ctx: &mut impl AsStoreMut, slice: &[f64]) -> Result { Ok(Self::from_array(ctx, slice.try_into()?)) } #[allow(unused_mut)] #[allow(clippy::missing_safety_doc)] - unsafe fn into_array(self, mut _ctx: &mut impl AsContextMut) -> Self::Array { + unsafe fn into_array(self, mut _ctx: &mut impl AsStoreMut) -> Self::Array { // Unpack items of the tuple. #[allow(non_snake_case)] let ( $( $x ),* ) = self; @@ -904,7 +920,7 @@ mod inner { #[allow(unused_mut)] #[allow(clippy::unused_unit)] #[allow(clippy::missing_safety_doc)] - unsafe fn from_c_struct(mut _ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self { + unsafe fn from_c_struct(mut _ctx: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self { // Unpack items of the C structure. #[allow(non_snake_case)] let $c_struct_name( $( $x ),* ) = c_struct; @@ -918,7 +934,7 @@ mod inner { #[allow(unused_parens, non_snake_case, unused_mut)] #[allow(clippy::missing_safety_doc)] - unsafe fn into_c_struct(self, mut _ctx: &mut impl AsContextMut) -> Self::CStruct { + unsafe fn into_c_struct(self, mut _ctx: &mut impl AsStoreMut) -> Self::CStruct { // Unpack items of the tuple. let ( $( $x ),* ) = self; @@ -961,30 +977,35 @@ mod inner { $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, + T: Send + 'static, + Func: Fn(FunctionEnvMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, { #[allow(non_snake_case)] fn function_body_ptr(self) -> *const VMFunctionBody { /// This is a function that wraps the real host /// function. Its address will be used inside the /// runtime. - unsafe extern "C" fn func_wrapper( ctx_ptr: usize, $( $x: <$x::Native as NativeWasmType>::Abi, )* ) -> Rets::CStruct + unsafe extern "C" fn func_wrapper( store_ptr: usize, handle_index: usize, $( $x: <$x::Native as NativeWasmType>::Abi, )* ) -> Rets::CStruct where $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, + T: Send + 'static, + Func: Fn(FunctionEnvMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, { + // let env: &Env = unsafe { &*(ptr as *const u8 as *const Env) }; let func: &Func = &*(&() as *const () as *const Func); - let mut ctx = ContextMut::from_raw(ctx_ptr as *mut ContextInner); - let mut ctx2 = ContextMut::from_raw(ctx_ptr as *mut ContextInner); + let mut store = StoreMut::from_raw(store_ptr as *mut _); + let mut store2 = StoreMut::from_raw(store_ptr as *mut _); let result = panic::catch_unwind(AssertUnwindSafe(|| { - func(ctx2.as_context_mut(), $( FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(&mut ctx, $x)) ),* ).into_result() + let handle: StoreHandle = StoreHandle::from_internal(store2.objects_mut().id(), InternalStoreHandle::from_index(handle_index).unwrap()); + let ctx: FunctionEnvMut = FunctionEnv::from_handle(handle).into_mut(&mut store2); + func(ctx, $( FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(&mut store, $x)) ),* ).into_result() })); match result { - Ok(Ok(result)) => return result.into_c_struct(&mut ctx), + Ok(Ok(result)) => return result.into_c_struct(&mut store), #[allow(deprecated)] Ok(Err(trap)) => RuntimeError::raise(Box::new(trap)), Err(_panic) => unimplemented!(), @@ -1051,18 +1072,18 @@ mod inner { 0 } - unsafe fn from_array(_: &mut impl AsContextMut, _: Self::Array) -> Self { + unsafe fn from_array(_: &mut impl AsStoreMut, _: Self::Array) -> Self { unreachable!() } unsafe fn from_slice( - _: &mut impl AsContextMut, + _: &mut impl AsStoreMut, _: &[f64], ) -> Result { unreachable!() } - unsafe fn into_array(self, _: &mut impl AsContextMut) -> Self::Array { + unsafe fn into_array(self, _: &mut impl AsStoreMut) -> Self::Array { [] } @@ -1070,11 +1091,11 @@ mod inner { [] } - unsafe fn from_c_struct(_: &mut impl AsContextMut, self_: Self::CStruct) -> Self { + unsafe fn from_c_struct(_: &mut impl AsStoreMut, self_: Self::CStruct) -> Self { self_ } - unsafe fn into_c_struct(self, _: &mut impl AsContextMut) -> Self::CStruct { + unsafe fn into_c_struct(self, _: &mut impl AsStoreMut) -> Self::CStruct { self } diff --git a/lib/api/src/js/externals/global.rs b/lib/api/src/js/externals/global.rs index c570c7b27d9..47f4446a254 100644 --- a/lib/api/src/js/externals/global.rs +++ b/lib/api/src/js/externals/global.rs @@ -1,7 +1,7 @@ -use crate::js::context::{AsContextMut, AsContextRef, ContextHandle, InternalContextHandle}; use crate::js::export::VMGlobal; use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; +use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle}; use crate::js::value::Value; use crate::js::wasm_bindgen_polyfill::Global as JSGlobal; use crate::js::GlobalType; @@ -17,7 +17,7 @@ use wasm_bindgen::JsValue; /// Spec: #[derive(Debug, Clone, PartialEq)] pub struct Global { - pub(crate) handle: ContextHandle, + pub(crate) handle: StoreHandle, } impl Global { @@ -27,14 +27,14 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let g = Global::new(&store, Value::I32(1)); /// /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Const); /// ``` - pub fn new(ctx: &mut impl AsContextMut, val: Value) -> Self { + pub fn new(ctx: &mut impl AsStoreMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Const).unwrap() } @@ -44,26 +44,26 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let g = Global::new_mut(&store, Value::I32(1)); /// /// assert_eq!(g.get(), Value::I32(1)); /// assert_eq!(g.ty().mutability, Mutability::Var); /// ``` - pub fn new_mut(ctx: &mut impl AsContextMut, val: Value) -> Self { + pub fn new_mut(ctx: &mut impl AsStoreMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Var).unwrap() } /// Create a `Global` with the initial value [`Value`] and the provided [`Mutability`]. fn from_value( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, val: Value, mutability: Mutability, ) -> Result { - if !val.is_from_context(ctx) { + if !val.is_from_store(ctx) { return Err(RuntimeError::new( - "cross-`Context` values are not supported", + "cross-`WasmerEnv` values are not supported", )); } let global_ty = GlobalType { @@ -99,7 +99,7 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Type, Value, GlobalType}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let c = Global::new(&store, Value::I32(1)); /// let v = Global::new_mut(&store, Value::I64(1)); @@ -107,8 +107,8 @@ impl Global { /// assert_eq!(c.ty(), &GlobalType::new(Type::I32, Mutability::Const)); /// assert_eq!(v.ty(), &GlobalType::new(Type::I64, Mutability::Var)); /// ``` - pub fn ty(&self, ctx: &impl AsContextRef) -> GlobalType { - self.handle.get(ctx.as_context_ref().objects()).ty + pub fn ty(&self, store: &impl AsStoreRef) -> GlobalType { + self.handle.get(store.as_store_ref().objects()).ty } /// Retrieves the current value [`Value`] that the Global has. @@ -117,23 +117,23 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let g = Global::new(&store, Value::I32(1)); /// /// assert_eq!(g.get(), Value::I32(1)); /// ``` - pub fn get(&self, ctx: &impl AsContextRef) -> Value { + pub fn get(&self, store: &impl AsStoreRef) -> Value { unsafe { let raw = self .handle - .get(ctx.as_context_ref().objects()) + .get(store.as_store_ref().objects()) .global .value() .as_f64() .unwrap(); - let ty = self.handle.get(ctx.as_context_ref().objects()).ty; - Value::from_raw(ctx, ty.ty, raw) + let ty = self.handle.get(store.as_store_ref().objects()).ty; + Value::from_raw(store, ty.ty, raw) } /* match self.vm_global.ty.ty { @@ -152,7 +152,7 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let g = Global::new_mut(&store, Value::I32(1)); /// @@ -169,7 +169,7 @@ impl Global { /// /// ```should_panic /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let g = Global::new(&store, Value::I32(1)); /// @@ -180,20 +180,20 @@ impl Global { /// /// ```should_panic /// # use wasmer::{Global, Store, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let g = Global::new(&store, Value::I32(1)); /// /// // This results in an error: `RuntimeError`. /// g.set(Value::I64(2)).unwrap(); /// ``` - pub fn set(&self, ctx: &mut impl AsContextMut, val: Value) -> Result<(), RuntimeError> { - if !val.is_from_context(ctx) { + pub fn set(&self, store: &mut impl AsStoreMut, val: Value) -> Result<(), RuntimeError> { + if !val.is_from_store(store) { return Err(RuntimeError::new( - "cross-`Context` values are not supported", + "cross-`WasmerEnv` values are not supported", )); } - let global_ty = self.ty(&ctx); + let global_ty = self.ty(&store); if global_ty.mutability == Mutability::Const { return Err(RuntimeError::new("The global is immutable".to_owned())); } @@ -212,32 +212,32 @@ impl Global { } }; self.handle - .get_mut(ctx.as_context_mut().objects_mut()) + .get_mut(store.objects_mut()) .global .set_value(&new_value); Ok(()) } - pub(crate) fn from_vm_export(ctx: &mut impl AsContextMut, vm_global: VMGlobal) -> Self { + pub(crate) fn from_vm_export(store: &mut impl AsStoreMut, vm_global: VMGlobal) -> Self { Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_global), + handle: StoreHandle::new(store.objects_mut(), vm_global), } } pub(crate) fn from_vm_extern( - ctx: &mut impl AsContextMut, - internal: InternalContextHandle, + store: &mut impl AsStoreMut, + internal: InternalStoreHandle, ) -> Self { Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(store.as_store_ref().objects().id(), internal) }, } } - /// Checks whether this `Global` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + /// Checks whether this `Global` can be used with the given store. + pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool { + self.handle.store_id() == store.as_store_ref().objects().id() } } diff --git a/lib/api/src/js/externals/memory.rs b/lib/api/src/js/externals/memory.rs index d100208c715..59cc788874a 100644 --- a/lib/api/src/js/externals/memory.rs +++ b/lib/api/src/js/externals/memory.rs @@ -1,9 +1,7 @@ -use crate::js::context::{ - AsContextMut, AsContextRef, ContextHandle, ContextObjects, InternalContextHandle, -}; use crate::js::export::VMMemory; use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; +use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreObjects}; use crate::js::{MemoryAccessError, MemoryType}; use std::convert::TryInto; use std::marker::PhantomData; @@ -80,7 +78,7 @@ extern "C" { /// Spec: #[derive(Debug, Clone)] pub struct Memory { - pub(crate) handle: ContextHandle, + pub(crate) handle: StoreHandle, #[allow(dead_code)] view: js_sys::Uint8Array, } @@ -98,11 +96,11 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); /// ``` - pub fn new(ctx: &mut impl AsContextMut, ty: MemoryType) -> Result { + pub fn new(ctx: &mut impl AsStoreMut, ty: MemoryType) -> Result { let descriptor = js_sys::Object::new(); js_sys::Reflect::set(&descriptor, &"initial".into(), &ty.minimum.0.into()).unwrap(); if let Some(max) = ty.maximum { @@ -123,15 +121,15 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let mt = MemoryType::new(1, None, false); /// let m = Memory::new(&store, mt).unwrap(); /// /// assert_eq!(m.ty(), mt); /// ``` - pub fn ty(&self, ctx: &impl AsContextRef) -> MemoryType { - self.handle.get(ctx.as_context_ref().objects()).ty + pub fn ty(&self, ctx: &impl AsStoreRef) -> MemoryType { + self.handle.get(ctx.as_store_ref().objects()).ty } /// Returns the pointer to the raw bytes of the `Memory`. @@ -141,11 +139,11 @@ impl Memory { } /// Returns the size (in bytes) of the `Memory`. - pub fn data_size(&self, ctx: &impl AsContextRef) -> u64 { + pub fn data_size(&self, ctx: &impl AsStoreRef) -> u64 { js_sys::Reflect::get( &self .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .memory .buffer(), &"byteLength".into(), @@ -161,17 +159,17 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let m = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); /// /// assert_eq!(m.size(), Pages(1)); /// ``` - pub fn size(&self, ctx: &impl AsContextRef) -> Pages { + pub fn size(&self, ctx: &impl AsStoreRef) -> Pages { let bytes = js_sys::Reflect::get( &self .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .memory .buffer(), &"byteLength".into(), @@ -189,7 +187,7 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let m = Memory::new(&store, MemoryType::new(1, Some(3), false)).unwrap(); /// let p = m.grow(2).unwrap(); @@ -205,7 +203,7 @@ impl Memory { /// /// ```should_panic /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES}; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # /// let m = Memory::new(&store, MemoryType::new(1, Some(1), false)).unwrap(); /// @@ -214,20 +212,19 @@ impl Memory { /// ``` pub fn grow( &self, - ctx: &mut impl AsContextMut, + store: &mut impl AsStoreMut, delta: IntoPages, ) -> Result where IntoPages: Into, { let pages = delta.into(); - let mut ctx_mut = ctx.as_context_mut(); - let js_memory = &self.handle.get_mut(ctx_mut.objects_mut()).memory; + let js_memory = &self.handle.get_mut(store.objects_mut()).memory; let our_js_memory: &JSMemory = JsCast::unchecked_from_js_ref(js_memory); let new_pages = our_js_memory.grow(pages.0).map_err(|err| { if err.is_instance_of::() { MemoryError::CouldNotGrow { - current: self.size(&ctx.as_context_ref()), + current: self.size(&store.as_store_ref()), attempted_delta: pages, } } else { @@ -239,40 +236,40 @@ impl Memory { /// Used by tests #[doc(hidden)] - pub fn uint8view(&self, ctx: &impl AsContextRef) -> js_sys::Uint8Array { + pub fn uint8view(&self, ctx: &impl AsStoreRef) -> js_sys::Uint8Array { js_sys::Uint8Array::new( &self .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .memory .buffer(), ) } - pub(crate) fn buffer<'a>(&'a self, _ctx: &'a impl AsContextRef) -> MemoryBuffer<'a> { + pub(crate) fn buffer<'a>(&'a self, _ctx: &'a impl AsStoreRef) -> MemoryBuffer<'a> { MemoryBuffer { base: &self.view as *const _ as *mut _, marker: PhantomData, } } - pub(crate) fn from_vm_export(ctx: &mut impl AsContextMut, vm_memory: VMMemory) -> Self { + pub(crate) fn from_vm_export(ctx: &mut impl AsStoreMut, vm_memory: VMMemory) -> Self { let view = js_sys::Uint8Array::new(&vm_memory.memory.buffer()); Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_memory), + handle: StoreHandle::new(ctx.objects_mut(), vm_memory), view, } } pub(crate) fn from_vm_extern( - ctx: &mut impl AsContextMut, - internal: InternalContextHandle, + ctx: &mut impl AsStoreMut, + internal: InternalStoreHandle, ) -> Self { let view = - js_sys::Uint8Array::new(&internal.get(ctx.as_context_ref().objects()).memory.buffer()); + js_sys::Uint8Array::new(&internal.get(ctx.as_store_ref().objects()).memory.buffer()); Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(ctx.as_store_ref().objects().id(), internal) }, view, } @@ -287,7 +284,7 @@ impl Memory { /// concurrent writes. pub fn read( &self, - _ctx: &impl AsContextRef, + _ctx: &impl AsStoreRef, offset: u64, data: &mut [u8], ) -> Result<(), MemoryAccessError> { @@ -317,7 +314,7 @@ impl Memory { /// concurrent writes. pub fn read_uninit<'a>( &self, - _ctx: &impl AsContextRef, + _ctx: &impl AsStoreRef, offset: u64, buf: &'a mut [MaybeUninit], ) -> Result<&'a mut [u8], MemoryAccessError> { @@ -352,7 +349,7 @@ impl Memory { /// concurrent reads/writes. pub fn write( &self, - _ctx: &mut impl AsContextMut, + _ctx: &mut impl AsStoreMut, offset: u64, data: &[u8], ) -> Result<(), MemoryAccessError> { @@ -371,8 +368,8 @@ impl Memory { } /// Checks whether this `Global` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { + self.handle.store_id() == ctx.as_store_ref().objects().id() } } @@ -389,7 +386,7 @@ impl<'a> Exportable<'a> for Memory { #[derive(Copy, Clone)] pub(crate) struct MemoryBuffer<'a> { base: *mut js_sys::Uint8Array, - marker: PhantomData<(&'a Memory, &'a ContextObjects)>, + marker: PhantomData<(&'a Memory, &'a StoreObjects)>, } impl<'a> MemoryBuffer<'a> { diff --git a/lib/api/src/js/externals/mod.rs b/lib/api/src/js/externals/mod.rs index 03c76ada645..ef34a5cc175 100644 --- a/lib/api/src/js/externals/mod.rs +++ b/lib/api/src/js/externals/mod.rs @@ -8,10 +8,10 @@ pub use self::global::Global; pub use self::memory::{Memory, MemoryError}; pub use self::table::Table; -use crate::js::context::{AsContextMut, AsContextRef}; use crate::js::export::Export; use crate::js::exports::{ExportError, Exportable}; use crate::js::store::StoreObject; +use crate::js::store::{AsStoreMut, AsStoreRef}; use crate::js::types::AsJs; use crate::js::ExternType; use std::fmt; @@ -34,7 +34,7 @@ pub enum Extern { impl Extern { /// Return the underlying type of the inner `Extern`. - pub fn ty(&self, ctx: &impl AsContextRef) -> ExternType { + pub fn ty(&self, ctx: &impl AsStoreRef) -> ExternType { match self { Self::Function(ft) => ExternType::Function(ft.ty(ctx).clone()), Self::Memory(ft) => ExternType::Memory(ft.ty(ctx)), @@ -44,7 +44,7 @@ impl Extern { } /// Create an `Extern` from an `wasmer_compiler::Export`. - pub fn from_vm_export(ctx: &mut impl AsContextMut, export: Export) -> Self { + pub fn from_vm_export(ctx: &mut impl AsStoreMut, export: Export) -> Self { match export { Export::Function(f) => Self::Function(Function::from_vm_extern(ctx, f)), Export::Memory(m) => Self::Memory(Memory::from_vm_extern(ctx, m)), @@ -54,12 +54,12 @@ impl Extern { } /// Checks whether this `Extern` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { match self { - Self::Function(val) => val.is_from_context(ctx), - Self::Memory(val) => val.is_from_context(ctx), - Self::Global(val) => val.is_from_context(ctx), - Self::Table(val) => val.is_from_context(ctx), + Self::Function(val) => val.is_from_store(ctx), + Self::Memory(val) => val.is_from_store(ctx), + Self::Global(val) => val.is_from_store(ctx), + Self::Table(val) => val.is_from_store(ctx), } } @@ -74,7 +74,7 @@ impl Extern { } impl AsJs for Extern { - fn as_jsvalue(&self, ctx: &impl AsContextRef) -> wasm_bindgen::JsValue { + fn as_jsvalue(&self, ctx: &impl AsStoreRef) -> wasm_bindgen::JsValue { match self { Self::Function(_) => self.to_export().as_jsvalue(ctx), Self::Global(_) => self.to_export().as_jsvalue(ctx), diff --git a/lib/api/src/js/externals/table.rs b/lib/api/src/js/externals/table.rs index f779b02d351..dd9143f2fd7 100644 --- a/lib/api/src/js/externals/table.rs +++ b/lib/api/src/js/externals/table.rs @@ -1,7 +1,7 @@ -use crate::js::context::{AsContextMut, AsContextRef, ContextHandle, InternalContextHandle}; use crate::js::export::{VMFunction, VMTable}; use crate::js::exports::{ExportError, Exportable}; use crate::js::externals::Extern; +use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle}; use crate::js::value::Value; use crate::js::RuntimeError; use crate::js::{FunctionType, TableType}; @@ -18,21 +18,21 @@ use js_sys::Function; /// Spec: #[derive(Debug, Clone, PartialEq)] pub struct Table { - pub(crate) handle: ContextHandle, + pub(crate) handle: StoreHandle, } fn set_table_item(table: &VMTable, item_index: u32, item: &Function) -> Result<(), RuntimeError> { table.table.set(item_index, item).map_err(|e| e.into()) } -fn get_function(ctx: &mut impl AsContextMut, val: Value) -> Result { - if !val.is_from_context(ctx) { +fn get_function(ctx: &mut impl AsStoreMut, val: Value) -> Result { + if !val.is_from_store(ctx) { return Err(RuntimeError::new("cannot pass Value across contexts")); } match val { Value::FuncRef(Some(ref func)) => Ok(func .handle - .get(&ctx.as_context_ref().objects()) + .get(&ctx.as_store_ref().objects()) .function .clone() .into()), @@ -49,11 +49,11 @@ impl Table { /// This function will construct the `Table` using the store /// [`BaseTunables`][crate::js::tunables::BaseTunables]. pub fn new( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, ty: TableType, init: Value, ) -> Result { - let mut ctx = ctx.as_context_mut(); + let mut ctx = ctx; let descriptor = js_sys::Object::new(); js_sys::Reflect::set(&descriptor, &"initial".into(), &ty.minimum.into())?; if let Some(max) = ty.maximum { @@ -71,20 +71,20 @@ impl Table { } Ok(Self { - handle: ContextHandle::new(ctx.objects_mut(), table), + handle: StoreHandle::new(ctx.objects_mut(), table), }) } /// Returns the [`TableType`] of the `Table`. - pub fn ty(&self, ctx: &impl AsContextRef) -> TableType { - self.handle.get(ctx.as_context_ref().objects()).ty + pub fn ty(&self, ctx: &impl AsStoreRef) -> TableType { + self.handle.get(ctx.as_store_ref().objects()).ty } /// Retrieves an element of the table at the provided `index`. - pub fn get(&self, ctx: &mut impl AsContextMut, index: u32) -> Option { + pub fn get(&self, ctx: &mut impl AsStoreMut, index: u32) -> Option { if let Some(func) = self .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .table .get(index) .ok() @@ -101,24 +101,17 @@ impl Table { /// Sets an element `val` in the Table at the provided `index`. pub fn set( &self, - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, index: u32, val: Value, ) -> Result<(), RuntimeError> { let item = get_function(ctx, val)?; - set_table_item( - self.handle.get_mut(ctx.as_context_mut().objects_mut()), - index, - &item, - ) + set_table_item(self.handle.get_mut(ctx.objects_mut()), index, &item) } /// Retrieves the size of the `Table` (in elements) - pub fn size(&self, ctx: &impl AsContextRef) -> u32 { - self.handle - .get(ctx.as_context_ref().objects()) - .table - .length() + pub fn size(&self, ctx: &impl AsStoreRef) -> u32 { + self.handle.get(ctx.as_store_ref().objects()).table.length() } /// Grows the size of the `Table` by `delta`, initializating @@ -130,7 +123,12 @@ impl Table { /// # Errors /// /// Returns an error if the `delta` is out of bounds for the table. - pub fn grow(&self, _delta: u32, _init: Value) -> Result { + pub fn grow( + &self, + store: &mut AsStoreMut, + _delta: u32, + _init: Value, + ) -> Result { unimplemented!(); } @@ -152,19 +150,19 @@ impl Table { } pub(crate) fn from_vm_extern( - ctx: &mut impl AsContextMut, - internal: InternalContextHandle, + ctx: &mut impl AsStoreMut, + internal: InternalStoreHandle, ) -> Self { Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(ctx.as_store_ref().objects().id(), internal) }, } } /// Checks whether this `Table` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { + self.handle.store_id() == ctx.as_store_ref().objects().id() } /// Get access to the backing VM value for this extern. This function is for @@ -177,9 +175,9 @@ impl Table { #[doc(hidden)] pub unsafe fn get_vm_table<'context>( &self, - ctx: &'context impl AsContextRef, + ctx: &'context impl AsStoreRef, ) -> &'context VMTable { - self.handle.get(ctx.as_context_ref().objects()) + self.handle.get(ctx.as_store_ref().objects()) } } diff --git a/lib/api/src/js/function_env.rs b/lib/api/src/js/function_env.rs new file mode 100644 index 00000000000..81ef590a7c2 --- /dev/null +++ b/lib/api/src/js/function_env.rs @@ -0,0 +1,153 @@ +use std::{any::Any, marker::PhantomData}; + +use crate::js::{StoreHandle, StoreObjects}; + +use crate::js::{AsStoreMut, AsStoreRef, StoreMut, StoreRef}; + +#[derive(Debug)] +#[repr(transparent)] +/// An opaque reference to a function environment. +/// The function environment data is owned by the `Store`. +pub struct FunctionEnv { + pub(crate) handle: StoreHandle, + _phantom: PhantomData, +} + +impl FunctionEnv { + /// Make a new extern reference + pub fn new(store: &mut impl AsStoreMut, value: T) -> Self + where + T: Any + Send + 'static + Sized, + { + Self { + handle: StoreHandle::new( + store.as_store_mut().objects_mut(), + VMFunctionEnvironment::new(value), + ), + _phantom: PhantomData, + } + } + + pub(crate) fn from_handle(handle: StoreHandle) -> Self { + Self { + handle, + _phantom: PhantomData, + } + } + + /// Get the data as reference + pub fn as_ref<'a>(&self, store: &'a impl AsStoreMut) -> &'a T + where + T: Any + Send + 'static + Sized, + { + self.handle + .get(store.as_store_ref().objects()) + .as_ref() + .downcast_ref::() + .unwrap() + } + + /// Get the data as mutable + pub fn as_mut<'a>(&self, store: &'a mut impl AsStoreMut) -> &'a mut T + where + T: Any + Send + 'static + Sized, + { + self.handle + .get_mut(store.objects_mut()) + .as_mut() + .downcast_mut::() + .unwrap() + } + + /// Convert it into a `FunctionEnvMut` + pub fn into_mut(self, store: &mut impl AsStoreMut) -> FunctionEnvMut + where + T: Any + Send + 'static + Sized, + { + FunctionEnvMut { + store_mut: store.as_store_mut(), + func_env: self, + } + } +} + +impl Clone for FunctionEnv { + fn clone(&self) -> Self { + Self { + handle: self.handle.clone(), + _phantom: self._phantom, + } + } +} + +/// A temporary handle to a [`Context`]. +pub struct FunctionEnvMut<'a, T: 'a> { + pub(crate) store_mut: StoreMut<'a>, + pub(crate) func_env: FunctionEnv, +} + +impl FunctionEnvMut<'_, T> { + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &T { + self.func_env.as_ref(&self.store_mut) + } + + /// Returns a mutable- reference to the host state in this context. + pub fn data_mut<'a>(&'a mut self) -> &'a mut T { + self.func_env.as_mut(&mut self.store_mut) + } + + /// Borrows a new mutable reference + pub fn as_mut<'a>(&'a mut self) -> FunctionEnvMut<'a, T> { + FunctionEnvMut { + store_mut: self.store_mut.as_store_mut(), + func_env: self.func_env.clone(), + } + } +} + +impl AsStoreRef for FunctionEnvMut<'_, T> { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { + inner: self.store_mut.inner, + } + } +} + +impl AsStoreMut for FunctionEnvMut<'_, T> { + fn as_store_mut(&mut self) -> StoreMut<'_> { + StoreMut { + inner: self.store_mut.inner, + } + } + #[inline] + fn objects_mut(&mut self) -> &mut StoreObjects { + &mut self.store_mut.inner.objects + } +} + +/// Underlying FunctionEnvironment used by a `VMFunction`. +pub struct VMFunctionEnvironment { + contents: Box, +} + +impl VMFunctionEnvironment { + /// Wraps the given value to expose it to Wasm code as a function context. + pub fn new(val: impl Any + Send + 'static) -> Self { + Self { + contents: Box::new(val), + } + } + + #[allow(clippy::should_implement_trait)] + /// Returns a reference to the underlying value. + pub fn as_ref(&self) -> &(dyn Any + Send + 'static) { + &*self.contents + } + + #[allow(clippy::should_implement_trait)] + /// Returns a mutable reference to the underlying value. + pub fn as_mut(&mut self) -> &mut (dyn Any + Send + 'static) { + &mut *self.contents + } +} diff --git a/lib/api/src/js/imports.rs b/lib/api/src/js/imports.rs index 596336e62ef..2c43350c5c0 100644 --- a/lib/api/src/js/imports.rs +++ b/lib/api/src/js/imports.rs @@ -1,10 +1,10 @@ //! The import module contains the implementation data structures and helper functions used to //! manipulate and access a wasm module's imports including memories, tables, globals, and //! functions. -use crate::js::context::AsContextRef; use crate::js::error::InstantiationError; use crate::js::exports::Exports; use crate::js::module::Module; +use crate::js::store::AsStoreRef; use crate::js::types::AsJs; use crate::Extern; use std::collections::HashMap; @@ -97,7 +97,7 @@ impl Imports { /// /// # Usage /// ```no_run - /// # let store = Default::default(); + /// # let mut store = Default::default(); /// use wasmer::{Imports, Function}; /// fn foo(n: i32) -> i32 { /// n @@ -151,7 +151,7 @@ impl Imports { } /// Returns the `Imports` as a Javascript `Object` - pub fn as_jsobject(&self, ctx: &impl AsContextRef) -> js_sys::Object { + pub fn as_jsobject(&self, ctx: &impl AsStoreRef) -> js_sys::Object { let imports = js_sys::Object::new(); let namespaces: HashMap<&str, Vec<(&str, &Extern)>> = self.map @@ -235,7 +235,7 @@ impl fmt::Debug for Imports { /// /// ``` /// # use wasmer::{Function, Store}; -/// # let store = Store::default(); +/// # let mut store = Store::default(); /// use wasmer::imports; /// /// let import_object = imports! { @@ -300,7 +300,7 @@ mod test { use crate::js::export::Export; use wasm_bindgen_test::*; fn namespace() { - let store = Store::default(); + let mut store = Store::default(); let g1 = Global::new(&store, Val::I32(0)); let namespace = namespace! { "happy" => g1 @@ -323,7 +323,7 @@ mod test { fn imports_macro_allows_trailing_comma_and_none() { use crate::js::Function; - let store = Default::default(); + let mut store = Default::default(); fn func(arg: i32) -> i32 { arg + 1 @@ -372,7 +372,7 @@ mod test { } fn chaining_works() { - let store = Store::default(); + let mut store = Store::default(); let g = Global::new(&store, Val::I32(0)); let mut imports1 = imports! { @@ -402,7 +402,7 @@ mod test { } fn extending_conflict_overwrites() { - let store = Store::default(); + let mut store = Store::default(); let g1 = Global::new(&store, Val::I32(0)); let g2 = Global::new(&store, Val::F32(0.)); @@ -430,7 +430,7 @@ mod test { ); // now test it in reverse - let store = Store::default(); + let mut store = Store::default(); let g1 = Global::new(&store, Val::I32(0)); let g2 = Global::new(&store, Val::F32(0.)); diff --git a/lib/api/src/js/instance.rs b/lib/api/src/js/instance.rs index ca2c830d7e3..181ccff54f9 100644 --- a/lib/api/src/js/instance.rs +++ b/lib/api/src/js/instance.rs @@ -1,10 +1,10 @@ -use crate::js::context::{AsContextMut, AsContextRef, ContextHandle}; use crate::js::error::InstantiationError; use crate::js::export::Export; use crate::js::exports::Exports; use crate::js::externals::Extern; use crate::js::imports::Imports; use crate::js::module::Module; +use crate::js::store::{AsStoreMut, AsStoreRef, StoreHandle}; use js_sys::WebAssembly; use std::fmt; @@ -18,7 +18,7 @@ use std::fmt; /// Spec: #[derive(Clone)] pub struct Instance { - _handle: ContextHandle, + _handle: StoreHandle, module: Module, #[allow(dead_code)] imports: Imports, @@ -41,7 +41,7 @@ impl Instance { /// ``` /// # use wasmer::{imports, Store, Module, Global, Value, Instance}; /// # fn main() -> anyhow::Result<()> { - /// let store = Store::default(); + /// let mut store = Store::default(); /// let module = Module::new(&store, "(module)")?; /// let imports = imports!{ /// "host" => { @@ -61,13 +61,13 @@ impl Instance { /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. pub fn new( - ctx: &mut impl AsContextMut, + mut ctx: &mut impl AsStoreMut, module: &Module, imports: &Imports, ) -> Result { let import_copy = imports.clone(); - let (instance, _imports): (ContextHandle, Vec) = module - .instantiate(&mut ctx.as_context_mut(), imports) + let (instance, _imports): (StoreHandle, Vec) = module + .instantiate(&mut ctx, imports) .map_err(|e| InstantiationError::Start(e))?; let self_instance = Self::from_module_and_instance(ctx, module, instance, import_copy)?; @@ -85,12 +85,12 @@ impl Instance { /// /// *This method is only available when targeting JS environments* pub fn from_module_and_instance( - ctx: &mut impl AsContextMut, + mut ctx: &mut impl AsStoreMut, module: &Module, - instance: ContextHandle, + instance: StoreHandle, imports: Imports, ) -> Result { - let instance_exports = instance.get(ctx.as_context_ref().objects()).exports(); + let instance_exports = instance.get(ctx.as_store_ref().objects()).exports(); let exports = module .exports() .map(|export_type| { @@ -104,9 +104,8 @@ impl Instance { )) })?; let export: Export = - Export::from_js_value(js_export, &mut ctx.as_context_mut(), extern_type)? - .into(); - let extern_ = Extern::from_vm_export(&mut ctx.as_context_mut(), export); + Export::from_js_value(js_export, &mut ctx, extern_type)?.into(); + let extern_ = Extern::from_vm_export(&mut ctx, export); Ok((name.to_string(), extern_)) }) .collect::>()?; @@ -126,11 +125,8 @@ impl Instance { /// Returns the inner WebAssembly Instance #[doc(hidden)] - pub fn raw<'context>( - &self, - ctx: &'context impl AsContextRef, - ) -> &'context WebAssembly::Instance { - &self._handle.get(ctx.as_context_ref().objects()) + pub fn raw<'context>(&self, ctx: &'context impl AsStoreRef) -> &'context WebAssembly::Instance { + &self._handle.get(ctx.as_store_ref().objects()) } } diff --git a/lib/api/src/js/js_import_object.rs b/lib/api/src/js/js_import_object.rs index f1e58aec906..e890c5bc144 100644 --- a/lib/api/src/js/js_import_object.rs +++ b/lib/api/src/js/js_import_object.rs @@ -1,5 +1,5 @@ -use crate::js::context::AsContextMut; use crate::js::error::WasmError; +use crate::js::store::AsStoreMut; use crate::js::{Export, ExternType, Module}; use std::collections::HashMap; @@ -53,7 +53,7 @@ impl JsImportObject { /// ``` pub fn get_export( &self, - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, module: &str, name: &str, ) -> Result { diff --git a/lib/api/src/js/mem_access.rs b/lib/api/src/js/mem_access.rs index e5eb45afb0a..f9416b067ab 100644 --- a/lib/api/src/js/mem_access.rs +++ b/lib/api/src/js/mem_access.rs @@ -1,7 +1,7 @@ -use crate::js::context::AsContextRef; use crate::js::externals::memory::MemoryBuffer; -use crate::RuntimeError; -use crate::{Memory, Memory32, Memory64, WasmPtr}; +use crate::js::store::AsStoreRef; +use crate::js::RuntimeError; +use crate::js::{Memory, Memory32, Memory64, WasmPtr}; use std::{ convert::TryInto, fmt, @@ -61,7 +61,7 @@ pub struct WasmRef<'a, T: ValueType> { impl<'a, T: ValueType> WasmRef<'a, T> { /// Creates a new `WasmRef` at the given offset in a memory. #[inline] - pub fn new(ctx: &'a impl AsContextRef, memory: &'a Memory, offset: u64) -> Self { + pub fn new(ctx: &'a impl AsStoreRef, memory: &'a Memory, offset: u64) -> Self { Self { buffer: memory.buffer(ctx), offset, @@ -160,7 +160,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { /// Returns a `MemoryAccessError` if the slice length overflows. #[inline] pub fn new( - ctx: &'a impl AsContextRef, + ctx: &'a impl AsStoreRef, memory: &'a Memory, offset: u64, len: u64, diff --git a/lib/api/src/js/mod.rs b/lib/api/src/js/mod.rs index 8f75409a87f..9863123c55b 100644 --- a/lib/api/src/js/mod.rs +++ b/lib/api/src/js/mod.rs @@ -23,11 +23,11 @@ mod lib { } } -mod context; mod error; mod export; mod exports; mod externals; +mod function_env; mod imports; mod instance; mod js_import_object; @@ -44,7 +44,6 @@ mod types; mod value; mod wasm_bindgen_polyfill; -pub use crate::js::context::{AsContextMut, AsContextRef, Context, ContextMut, ContextRef}; pub use crate::js::error::{DeserializeError, InstantiationError, SerializeError}; pub use crate::js::export::Export; pub use crate::js::exports::{ExportError, Exportable, Exports, ExportsIterator}; @@ -52,6 +51,7 @@ pub use crate::js::externals::{ Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, MemoryError, Table, WasmTypeList, }; +pub use crate::js::function_env::{FunctionEnv, FunctionEnvMut}; pub use crate::js::imports::Imports; pub use crate::js::instance::Instance; pub use crate::js::js_import_object::JsImportObject; @@ -62,7 +62,9 @@ pub use crate::js::native_type::NativeWasmTypeInto; pub use crate::js::ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64}; pub use crate::js::trap::RuntimeError; -pub use crate::js::store::{Store, StoreObject}; +pub use crate::js::store::{ + AsStoreMut, AsStoreRef, Store, StoreHandle, StoreMut, StoreObject, StoreObjects, StoreRef, +}; pub use crate::js::types::ValType as Type; pub use crate::js::types::{ ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability, diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index 67ef83b9aa1..209f46dfd46 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -1,4 +1,3 @@ -use crate::js::context::{AsContextMut, ContextHandle}; #[cfg(feature = "wat")] use crate::js::error::WasmError; use crate::js::error::{CompileError, InstantiationError}; @@ -7,8 +6,10 @@ use crate::js::error::{DeserializeError, SerializeError}; use crate::js::externals::Extern; use crate::js::imports::Imports; use crate::js::store::Store; +use crate::js::store::{AsStoreMut, StoreHandle}; use crate::js::types::{AsJs, ExportType, ImportType}; use crate::js::RuntimeError; +use crate::AsStoreRef; use js_sys::{Reflect, Uint8Array, WebAssembly}; use std::fmt; use std::io; @@ -59,7 +60,6 @@ pub struct ModuleTypeHints { /// contents rather than a deep copy. #[derive(Clone)] pub struct Module { - store: Store, module: WebAssembly::Module, name: Option, // WebAssembly type hints @@ -95,7 +95,7 @@ impl Module { /// ``` /// use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = "(module)"; /// let module = Module::new(&store, wat)?; /// # Ok(()) @@ -107,7 +107,7 @@ impl Module { /// ``` /// use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// // The following is the same as: /// // (module /// // (type $t0 (func (param i32) (result i32))) @@ -129,7 +129,7 @@ impl Module { /// # } /// ``` #[allow(unreachable_code)] - pub fn new(store: &Store, bytes: impl AsRef<[u8]>) -> Result { + pub fn new(_store: &impl AsStoreRef, bytes: impl AsRef<[u8]>) -> Result { #[cfg(feature = "wat")] let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| { CompileError::Wasm(WasmError::Generic(format!( @@ -137,11 +137,14 @@ impl Module { e ))) })?; - Self::from_binary(store, bytes.as_ref()) + Self::from_binary(_store, bytes.as_ref()) } /// Creates a new WebAssembly module from a file path. - pub fn from_file(_store: &Store, _file: impl AsRef) -> Result { + pub fn from_file( + _store: &impl AsStoreRef, + _file: impl AsRef, + ) -> Result { unimplemented!(); } @@ -150,10 +153,10 @@ impl Module { /// Opposed to [`Module::new`], this function is not compatible with /// the WebAssembly text format (if the "wat" feature is enabled for /// this crate). - pub fn from_binary(store: &Store, binary: &[u8]) -> Result { + pub fn from_binary(_store: &impl AsStoreRef, binary: &[u8]) -> Result { // // Self::validate(store, binary)?; - unsafe { Self::from_binary_unchecked(store, binary) } + unsafe { Self::from_binary_unchecked(_store, binary) } } /// Creates a new WebAssembly module skipping any kind of validation. @@ -163,7 +166,7 @@ impl Module { /// This is safe since the JS vm should be safe already. /// We maintain the `unsafe` to preserve the same API as Wasmer pub unsafe fn from_binary_unchecked( - store: &Store, + _store: &impl AsStoreRef, binary: &[u8], ) -> Result { let js_bytes = Uint8Array::view(binary); @@ -194,7 +197,6 @@ impl Module { let (type_hints, name) = (None, None); Ok(Self { - store: store.clone(), module, type_hints, name, @@ -209,7 +211,7 @@ impl Module { /// This validation is normally pretty fast and checks the enabled /// WebAssembly features in the Store Engine to assure deterministic /// validation of the Module. - pub fn validate(_store: &Store, binary: &[u8]) -> Result<(), CompileError> { + pub fn validate(_store: &impl AsStoreRef, binary: &[u8]) -> Result<(), CompileError> { let js_bytes = unsafe { Uint8Array::view(binary) }; match WebAssembly::validate(&js_bytes.into()) { Ok(true) => Ok(()), @@ -219,16 +221,17 @@ impl Module { pub(crate) fn instantiate( &self, - ctx: &mut impl AsContextMut, + store: &mut impl AsStoreMut, imports: &Imports, - ) -> Result<(ContextHandle, Vec), RuntimeError> { - // Ensure all imports come from the same context. + ) -> Result<(StoreHandle, Vec), RuntimeError> { + // Ensure all imports come from the same store. if imports .into_iter() - .any(|(_, import)| !import.is_from_context(ctx)) + .any(|(_, import)| !import.is_from_store(store)) { - // FIXME is RuntimeError::User appropriate? - return Err(RuntimeError::user(Box::new(InstantiationError::BadContext))); + return Err(RuntimeError::user(Box::new( + InstantiationError::DifferentStores, + ))); } let imports_object = js_sys::Object::new(); let mut import_externs: Vec = vec![]; @@ -241,7 +244,7 @@ impl Module { js_sys::Reflect::set( &val, &import_type.name().into(), - &import.as_jsvalue(&ctx.as_context_ref()), + &import.as_jsvalue(&store.as_store_ref()), )?; } else { // If the namespace doesn't exist @@ -249,7 +252,7 @@ impl Module { js_sys::Reflect::set( &import_namespace, &import_type.name().into(), - &import.as_jsvalue(&ctx.as_context_ref()), + &import.as_jsvalue(&store.as_store_ref()), )?; js_sys::Reflect::set( &imports_object, @@ -263,8 +266,8 @@ impl Module { // the error for us, so we don't need to handle it } Ok(( - ContextHandle::new( - ctx.as_context_mut().objects_mut(), + StoreHandle::new( + store.as_store_mut().objects_mut(), WebAssembly::Instance::new(&self.module, &imports_object) .map_err(|e: JsValue| -> RuntimeError { e.into() })?, ), @@ -282,7 +285,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = "(module $moduleName)"; /// let module = Module::new(&store, wat)?; /// assert_eq!(module.name(), Some("moduleName")); @@ -309,8 +312,11 @@ impl Module { /// This is safe since deserialization under `js` is essentially same as reconstructing `Module`. /// We maintain the `unsafe` to preserve the same API as Wasmer #[cfg(feature = "js-serializable-module")] - pub unsafe fn deserialize(store: &Store, bytes: &[u8]) -> Result { - Self::new(store, bytes).map_err(|e| DeserializeError::Compiler(e)) + pub unsafe fn deserialize( + _store: &impl AsStoreRef, + bytes: &[u8], + ) -> Result { + Self::new(_store, bytes).map_err(|e| DeserializeError::Compiler(e)) } /// Sets the name of the current module. @@ -325,7 +331,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = "(module)"; /// let mut module = Module::new(&store, wat)?; /// assert_eq!(module.name(), None); @@ -360,7 +366,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = r#"(module /// (import "host" "func1" (func)) /// (import "host" "func2" (func)) @@ -458,7 +464,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = r#"(module /// (func (export "namedfunc")) /// (memory (export "namedmemory") 1) @@ -530,11 +536,6 @@ impl Module { // pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator> + 'a { // unimplemented!(); // } - - /// Returns the [`Store`] where the `Instance` belongs. - pub fn store(&self) -> &Store { - &self.store - } } impl fmt::Debug for Module { @@ -548,7 +549,6 @@ impl fmt::Debug for Module { impl From for Module { fn from(module: WebAssembly::Module) -> Module { Module { - store: Store::default(), module, name: None, type_hints: None, diff --git a/lib/api/src/js/native.rs b/lib/api/src/js/native.rs index ca21f752301..588f9618254 100644 --- a/lib/api/src/js/native.rs +++ b/lib/api/src/js/native.rs @@ -9,8 +9,9 @@ //! ``` use std::marker::PhantomData; -use crate::js::context::{AsContextMut, AsContextRef, ContextHandle}; use crate::js::externals::Function; +use crate::js::store::{AsStoreMut, AsStoreRef, StoreHandle}; +use crate::js::FunctionEnv; use crate::js::{FromToNativeWasmType, RuntimeError, WasmTypeList}; // use std::panic::{catch_unwind, AssertUnwindSafe}; use crate::js::export::VMFunction; @@ -23,7 +24,7 @@ use wasm_bindgen::JsValue; /// (using the Native ABI). #[derive(Clone)] pub struct TypedFunction { - pub(crate) handle: ContextHandle, + pub(crate) handle: StoreHandle, _phantom: PhantomData<(Args, Rets)>, } @@ -36,9 +37,13 @@ where Rets: WasmTypeList, { #[allow(dead_code)] - pub(crate) fn new(ctx: &mut impl AsContextMut, vm_function: VMFunction) -> Self { + pub(crate) fn new( + store: &mut impl AsStoreMut, + env: &FunctionEnv, + vm_function: VMFunction, + ) -> Self { Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), + handle: StoreHandle::new(store.as_store_mut().objects_mut(), vm_function), _phantom: PhantomData, } } @@ -61,11 +66,11 @@ macro_rules! impl_native_traits { { /// Call the typed func and return results. #[allow(clippy::too_many_arguments)] - pub fn call(&self, ctx: &mut impl AsContextMut, $( $x: $x, )* ) -> Result where + pub fn call(&self, mut ctx: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result where $( $x: FromToNativeWasmType + crate::js::NativeWasmTypeInto, )* { - let params_list: Vec = vec![ $( JsValue::from_f64($x.into_raw(ctx))),* ]; - let results = self.handle.get(ctx.as_context_ref().objects()).function.apply( + let params_list: Vec = vec![ $( JsValue::from_f64($x.into_raw(&mut ctx))),* ]; + let results = self.handle.get(ctx.as_store_ref().objects()).function.apply( &JsValue::UNDEFINED, &Array::from_iter(params_list.iter()) )?; @@ -76,7 +81,7 @@ macro_rules! impl_native_traits { 1 => unsafe { let ty = Rets::wasm_types()[0]; let val = param_from_js(&ty, &results); - *mut_rets = val.as_raw(&mut ctx.as_context_mut()); + *mut_rets = val.as_raw(&mut ctx); } _n => { let results: Array = results.into(); @@ -85,7 +90,7 @@ macro_rules! impl_native_traits { unsafe { let val = param_from_js(&ret_type, &ret); let slot = mut_rets.add(i); - *slot = val.as_raw(&mut ctx.as_context_mut()); + *slot = val.as_raw(&mut ctx); } } } @@ -101,7 +106,7 @@ macro_rules! impl_native_traits { $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, { - fn get_self_from_extern_with_generics(ctx: &impl AsContextRef, _extern: &crate::js::externals::Extern) -> Result { + fn get_self_from_extern_with_generics(ctx: &impl AsStoreRef, _extern: &crate::js::externals::Extern) -> Result { use crate::js::exports::Exportable; crate::js::Function::get_self_from_extern(_extern)?.native(ctx).map_err(|_| crate::js::exports::ExportError::IncompatibleType) } diff --git a/lib/api/src/js/native_type.rs b/lib/api/src/js/native_type.rs index e6dc2805462..d2a3abc1b68 100644 --- a/lib/api/src/js/native_type.rs +++ b/lib/api/src/js/native_type.rs @@ -3,113 +3,113 @@ use wasmer_types::{NativeWasmType, Type}; -use crate::Function; +use crate::js::Function; -use super::context::AsContextMut; +use super::store::AsStoreMut; /// `NativeWasmTypeInto` performs conversions from and into `NativeWasmType` /// types with a context. pub trait NativeWasmTypeInto: NativeWasmType + Sized { #[doc(hidden)] - fn into_abi(self, ctx: &mut impl AsContextMut) -> Self::Abi; + fn into_abi(self, ctx: &mut impl AsStoreMut) -> Self::Abi; #[doc(hidden)] - unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self; + unsafe fn from_abi(ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self; /// Convert self to raw value representation. - fn into_raw(self, ctx: &mut impl AsContextMut) -> f64; + fn into_raw(self, ctx: &mut impl AsStoreMut) -> f64; /// Convert to self from raw value representation. /// /// # Safety /// - unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: f64) -> Self; + unsafe fn from_raw(ctx: &mut impl AsStoreMut, raw: f64) -> Self; } impl NativeWasmTypeInto for i32 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> f64 { self.into() } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: f64) -> Self { raw as _ } } impl NativeWasmTypeInto for i64 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> f64 { self as _ } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: f64) -> Self { raw as _ } } impl NativeWasmTypeInto for f32 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> f64 { self as _ } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: f64) -> Self { raw as _ } } impl NativeWasmTypeInto for f64 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> f64 { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> f64 { self } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: f64) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: f64) -> Self { raw } } diff --git a/lib/api/src/js/ptr.rs b/lib/api/src/js/ptr.rs index 95a1f8f1704..1e2af555f2f 100644 --- a/lib/api/src/js/ptr.rs +++ b/lib/api/src/js/ptr.rs @@ -1,7 +1,7 @@ -use crate::js::context::AsContextRef; +use crate::js::store::AsStoreRef; use crate::js::NativeWasmTypeInto; use crate::js::{externals::Memory, FromToNativeWasmType}; -use crate::{MemoryAccessError, WasmRef, WasmSlice}; +use crate::js::{MemoryAccessError, WasmRef, WasmSlice}; use std::convert::TryFrom; use std::{fmt, marker::PhantomData, mem}; pub use wasmer_types::Memory32; @@ -138,13 +138,13 @@ impl WasmPtr { /// Creates a `WasmRef` from this `WasmPtr` which allows reading and /// mutating of the value being pointed to. #[inline] - pub fn deref<'a>(self, ctx: &'a impl AsContextRef, memory: &'a Memory) -> WasmRef<'a, T> { + pub fn deref<'a>(self, ctx: &'a impl AsStoreRef, memory: &'a Memory) -> WasmRef<'a, T> { WasmRef::new(ctx, memory, self.offset.into()) } /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, ctx: &impl AsContextRef, memory: &Memory) -> Result { + pub fn read(self, ctx: &impl AsStoreRef, memory: &Memory) -> Result { self.deref(ctx, memory).read() } @@ -152,7 +152,7 @@ impl WasmPtr { #[inline] pub fn write( self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, memory: &Memory, val: T, ) -> Result<(), MemoryAccessError> { @@ -167,7 +167,7 @@ impl WasmPtr { #[inline] pub fn slice<'a>( self, - ctx: &'a impl AsContextRef, + ctx: &'a impl AsStoreRef, memory: &'a Memory, len: M::Offset, ) -> Result, MemoryAccessError> { @@ -181,7 +181,7 @@ impl WasmPtr { #[inline] pub fn read_until<'a>( self, - ctx: &'a impl AsContextRef, + ctx: &'a impl AsStoreRef, memory: &'a Memory, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { @@ -206,7 +206,7 @@ impl WasmPtr { #[inline] pub fn read_utf8_string<'a>( self, - ctx: &'a impl AsContextRef, + ctx: &'a impl AsStoreRef, memory: &'a Memory, len: M::Offset, ) -> Result { @@ -221,7 +221,7 @@ impl WasmPtr { #[inline] pub fn read_utf8_string_with_nul<'a>( self, - ctx: &'a impl AsContextRef, + ctx: &'a impl AsStoreRef, memory: &'a Memory, ) -> Result { let vec = self.read_until(ctx, memory, |&byte| byte == 0)?; diff --git a/lib/api/src/js/store.rs b/lib/api/src/js/store.rs index 88c8b068f78..a2553df7407 100644 --- a/lib/api/src/js/store.rs +++ b/lib/api/src/js/store.rs @@ -1,5 +1,12 @@ use std::fmt; +/// We require the context to have a fixed memory address for its lifetime since +/// various bits of the VM have raw pointers that point back to it. Hence we +/// wrap the actual context in a box. +pub(crate) struct StoreInner { + pub(crate) objects: StoreObjects, +} + /// The store represents all global state that can be manipulated by /// WebAssembly programs. It consists of the runtime representation /// of all instances of functions, tables, memories, and globals that @@ -10,13 +17,18 @@ use std::fmt; /// [`Tunables`] (that are used to create the memories, tables and globals). /// /// Spec: -#[derive(Clone)] -pub struct Store; +pub struct Store { + pub(crate) inner: Box, +} impl Store { /// Creates a new `Store`. pub fn new() -> Self { - Self + Self { + inner: Box::new(StoreInner { + objects: Default::default(), + }), + } } /// Checks whether two stores are identical. A store is considered @@ -57,3 +69,377 @@ pub trait StoreObject { true } } + +impl AsStoreRef for Store { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { inner: &self.inner } + } +} +impl AsStoreMut for Store { + fn as_store_mut(&mut self) -> StoreMut<'_> { + StoreMut { + inner: &mut self.inner, + } + } + fn objects_mut(&mut self) -> &mut StoreObjects { + &mut self.inner.objects + } +} + +/// A temporary handle to a [`Context`]. +pub struct StoreRef<'a> { + pub(crate) inner: &'a StoreInner, +} + +impl<'a> StoreRef<'a> { + pub(crate) fn objects(&self) -> &'a StoreObjects { + &self.inner.objects + } + + /// Checks whether two stores are identical. A store is considered + /// equal to another store if both have the same engine. The + /// tunables are excluded from the logic. + pub fn same(a: &Self, b: &Self) -> bool { + a.inner.objects.id() == b.inner.objects.id() + } +} + +/// A temporary handle to a [`Context`]. +pub struct StoreMut<'a> { + pub(crate) inner: &'a mut StoreInner, +} + +impl<'a> StoreMut<'a> { + /// Checks whether two stores are identical. A store is considered + /// equal to another store if both have the same engine. The + /// tunables are excluded from the logic. + pub fn same(a: &Self, b: &Self) -> bool { + a.inner.objects.id() == b.inner.objects.id() + } + + pub(crate) fn as_raw(&self) -> *mut StoreInner { + self.inner as *const StoreInner as *mut StoreInner + } + + pub(crate) unsafe fn from_raw(raw: *mut StoreInner) -> Self { + Self { inner: &mut *raw } + } +} + +/// Helper trait for a value that is convertible to a [`StoreRef`]. +pub trait AsStoreRef { + /// Returns a `StoreRef` pointing to the underlying context. + fn as_store_ref(&self) -> StoreRef<'_>; +} + +/// Helper trait for a value that is convertible to a [`StoreMut`]. +pub trait AsStoreMut: AsStoreRef { + /// Returns a `StoreMut` pointing to the underlying context. + fn as_store_mut(&mut self) -> StoreMut<'_>; + + /// Returns the ObjectMutable + fn objects_mut(&mut self) -> &mut StoreObjects; +} + +impl AsStoreRef for StoreRef<'_> { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { inner: self.inner } + } +} + +impl AsStoreRef for StoreMut<'_> { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { inner: self.inner } + } +} +impl AsStoreMut for StoreMut<'_> { + fn as_store_mut(&mut self) -> StoreMut<'_> { + StoreMut { inner: self.inner } + } + fn objects_mut(&mut self) -> &mut StoreObjects { + &mut self.inner.objects + } +} + +impl AsStoreRef for &'_ T { + fn as_store_ref(&self) -> StoreRef<'_> { + T::as_store_ref(*self) + } +} +impl AsStoreRef for &'_ mut T { + fn as_store_ref(&self) -> StoreRef<'_> { + T::as_store_ref(*self) + } +} +impl AsStoreMut for &'_ mut T { + fn as_store_mut(&mut self) -> StoreMut<'_> { + T::as_store_mut(*self) + } + fn objects_mut(&mut self) -> &mut StoreObjects { + T::objects_mut(*self) + } +} + +pub use objects::*; + +use crate::js::FunctionEnv; +mod objects { + use crate::js::{ + export::{VMFunction, VMGlobal, VMMemory, VMTable}, + function_env::VMFunctionEnvironment, + }; + use std::{ + cell::UnsafeCell, + fmt, + marker::PhantomData, + num::{NonZeroU64, NonZeroUsize}, + ptr::NonNull, + sync::atomic::{AtomicU64, Ordering}, + }; + + /// Unique ID to identify a context. + /// + /// Every handle to an object managed by a context also contains the ID of the + /// context. This is used to check that a handle is always used with the + /// correct context. + #[derive(Debug, Copy, Clone, Eq, PartialEq)] + pub struct StoreId(NonZeroU64); + + impl Default for StoreId { + // Allocates a unique ID for a new context. + fn default() -> Self { + // No overflow checking is needed here: overflowing this would take + // thousands of years. + static NEXT_ID: AtomicU64 = AtomicU64::new(1); + Self(NonZeroU64::new(NEXT_ID.fetch_add(1, Ordering::Relaxed)).unwrap()) + } + } + + /// Trait to represent an object managed by a context. This is implemented on + /// the VM types managed by the context. + pub trait StoreObject: Sized { + fn list(ctx: &StoreObjects) -> &Vec; + fn list_mut(ctx: &mut StoreObjects) -> &mut Vec; + } + + macro_rules! impl_store_object { + ($($field:ident => $ty:ty,)*) => { + $( + impl StoreObject for $ty { + fn list(ctx: &StoreObjects) -> &Vec { + &ctx.$field + } + fn list_mut(ctx: &mut StoreObjects) -> &mut Vec { + &mut ctx.$field + } + } + )* + }; +} + + impl_store_object! { + functions => VMFunction, + tables => VMTable, + globals => VMGlobal, + memories => VMMemory, + instances => js_sys::WebAssembly::Instance, + function_environments => VMFunctionEnvironment, + } + + /// Set of objects managed by a context. + #[derive(Default)] + pub struct StoreObjects { + id: StoreId, + memories: Vec, + tables: Vec, + globals: Vec, + functions: Vec, + instances: Vec, + function_environments: Vec, + } + + impl StoreObjects { + /// Returns the ID of this context. + pub fn id(&self) -> StoreId { + self.id + } + + /// Returns a pair of mutable references from two handles. + /// + /// Panics if both handles point to the same object. + pub fn get_2_mut( + &mut self, + a: InternalStoreHandle, + b: InternalStoreHandle, + ) -> (&mut T, &mut T) { + assert_ne!(a.index(), b.index()); + let list = T::list_mut(self); + if a.index() < b.index() { + let (low, high) = list.split_at_mut(b.index()); + (&mut low[a.index()], &mut high[0]) + } else { + let (low, high) = list.split_at_mut(a.index()); + (&mut high[0], &mut low[a.index()]) + } + } + } + + /// Handle to an object managed by a context. + /// + /// Internally this is just an integer index into a context. A reference to the + /// context must be passed in separately to access the actual object. + pub struct StoreHandle { + id: StoreId, + internal: InternalStoreHandle, + } + + impl core::cmp::PartialEq for StoreHandle { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } + } + impl Clone for StoreHandle { + fn clone(&self) -> Self { + Self { + id: self.id, + internal: self.internal, + } + } + } + + impl fmt::Debug for StoreHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("StoreHandle") + .field("id", &self.id) + .field("internal", &self.internal.index()) + .finish() + } + } + + impl StoreHandle { + /// Moves the given object into a context and returns a handle to it. + pub fn new(ctx: &mut StoreObjects, val: T) -> Self { + Self { + id: ctx.id, + internal: InternalStoreHandle::new(ctx, val), + } + } + + /// Returns a reference to the object that this handle points to. + pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T { + assert_eq!(self.id, ctx.id, "object used with the wrong context"); + self.internal.get(ctx) + } + + /// Returns a mutable reference to the object that this handle points to. + pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T { + assert_eq!(self.id, ctx.id, "object used with the wrong context"); + self.internal.get_mut(ctx) + } + + /// Returns the internal handle contains within this handle. + pub fn internal_handle(&self) -> InternalStoreHandle { + self.internal + } + + /// Returns the ID of the context associated with the handle. + pub fn store_id(&self) -> StoreId { + self.id + } + + /// Constructs a `StoreHandle` from a `StoreId` and an `InternalStoreHandle`. + /// + /// # Safety + /// Handling `InternalStoreHandle` values is unsafe because they do not track context ID. + pub unsafe fn from_internal(id: StoreId, internal: InternalStoreHandle) -> Self { + Self { id, internal } + } + } + + /// Internal handle to an object owned by the current context. + /// + /// Unlike `StoreHandle` this does not track the context ID: it is only + /// intended to be used within objects already owned by a context. + #[repr(transparent)] + pub struct InternalStoreHandle { + // Use a NonZero here to reduce the size of Option. + idx: NonZeroUsize, + marker: PhantomData T>, + } + + impl Clone for InternalStoreHandle { + fn clone(&self) -> Self { + *self + } + } + impl Copy for InternalStoreHandle {} + + impl fmt::Debug for InternalStoreHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("InternalStoreHandle") + .field("idx", &self.idx) + .finish() + } + } + impl PartialEq for InternalStoreHandle { + fn eq(&self, other: &Self) -> bool { + self.idx == other.idx + } + } + impl Eq for InternalStoreHandle {} + + impl InternalStoreHandle { + /// Moves the given object into a context and returns a handle to it. + pub fn new(ctx: &mut StoreObjects, val: T) -> Self { + let list = T::list_mut(ctx); + let idx = NonZeroUsize::new(list.len() + 1).unwrap(); + list.push(val); + Self { + idx, + marker: PhantomData, + } + } + + /// Returns a reference to the object that this handle points to. + pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T { + &T::list(ctx)[self.idx.get() - 1] + } + + /// Returns a mutable reference to the object that this handle points to. + pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T { + &mut T::list_mut(ctx)[self.idx.get() - 1] + } + + pub(crate) fn index(&self) -> usize { + self.idx.get() + } + + pub(crate) fn from_index(idx: usize) -> Option { + NonZeroUsize::new(idx).map(|idx| Self { + idx, + marker: PhantomData, + }) + } + } + + /// Data used by the generated code is generally located inline within the + /// `VMContext` for items defined in an instance. Host-defined objects are + /// allocated separately and owned directly by the context. + pub enum MaybeInstanceOwned { + /// The data is owned here. + Host(Box>), + + /// The data is stored inline in the `VMContext` of an instance. + Instance(NonNull), + } + + impl MaybeInstanceOwned { + /// Returns underlying pointer to the VM data. + pub fn as_ptr(&self) -> NonNull { + match self { + MaybeInstanceOwned::Host(p) => unsafe { NonNull::new_unchecked(p.get()) }, + MaybeInstanceOwned::Instance(p) => *p, + } + } + } +} diff --git a/lib/api/src/js/types.rs b/lib/api/src/js/types.rs index baf52038ddd..ebce0b27808 100644 --- a/lib/api/src/js/types.rs +++ b/lib/api/src/js/types.rs @@ -1,7 +1,7 @@ //use crate::js::externals::Function; // use crate::js::store::{Store, StoreObject}; // use crate::js::RuntimeError; -use crate::js::context::AsContextRef; +use crate::js::store::AsStoreRef; use crate::js::value::Value; use wasm_bindgen::JsValue; pub use wasmer_types::{ @@ -19,7 +19,7 @@ pub use wasmer_types::{ //pub type Value = Value; pub trait AsJs { - fn as_jsvalue(&self, ctx: &impl AsContextRef) -> JsValue; + fn as_jsvalue(&self, ctx: &impl AsStoreRef) -> JsValue; } #[inline] @@ -37,7 +37,7 @@ pub fn param_from_js(ty: &ValType, js_val: &JsValue) -> Value { } impl AsJs for Value { - fn as_jsvalue(&self, ctx: &impl AsContextRef) -> JsValue { + fn as_jsvalue(&self, ctx: &impl AsStoreRef) -> JsValue { match self { Self::I32(i) => JsValue::from_f64(*i as f64), Self::I64(i) => JsValue::from_f64(*i as f64), @@ -45,7 +45,7 @@ impl AsJs for Value { Self::F64(f) => JsValue::from_f64(*f), Self::FuncRef(Some(func)) => func .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .function .clone() .into(), diff --git a/lib/api/src/js/value.rs b/lib/api/src/js/value.rs index 703b6df4502..99188e20d98 100644 --- a/lib/api/src/js/value.rs +++ b/lib/api/src/js/value.rs @@ -7,7 +7,7 @@ use wasmer_types::Type; //use crate::ExternRef; use crate::js::externals::function::Function; -use super::context::AsContextRef; +use super::store::AsStoreRef; /// WebAssembly computations manipulate values of basic value types: /// * Integers (32 or 64 bit width) @@ -82,7 +82,7 @@ impl Value { } /// Converts the `Value` into a `f64`. - pub fn as_raw(&self, ctx: &impl AsContextRef) -> f64 { + pub fn as_raw(&self, ctx: &impl AsStoreRef) -> f64 { match *self { Self::I32(v) => v as f64, Self::I64(v) => v as f64, @@ -90,7 +90,7 @@ impl Value { Self::F64(v) => v, Self::FuncRef(Some(ref f)) => f .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .function .as_f64() .unwrap_or(0_f64), //TODO is this correct? @@ -105,7 +105,7 @@ impl Value { /// /// # Safety /// - pub unsafe fn from_raw(_ctx: &impl AsContextRef, ty: Type, raw: f64) -> Self { + pub unsafe fn from_raw(_ctx: &impl AsStoreRef, ty: Type, raw: f64) -> Self { match ty { Type::I32 => Self::I32(raw as i32), Type::I64 => Self::I64(raw as i64), @@ -128,7 +128,7 @@ impl Value { /// /// Externref and funcref values are tied to a context and can only be used /// with that context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { match self { Self::I32(_) | Self::I64(_) @@ -136,8 +136,8 @@ impl Value { | Self::F64(_) //| Self::ExternRef(None) | Self::FuncRef(None) => true, - //Self::ExternRef(Some(e)) => e.is_from_context(ctx), - Self::FuncRef(Some(f)) => f.is_from_context(ctx), + //Self::ExternRef(Some(e)) => e.is_from_store(ctx), + Self::FuncRef(Some(f)) => f.is_from_store(ctx), } } diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index dcdd56e3fe2..5a14ab0dab6 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -41,7 +41,7 @@ //! //! ```rust //! use wasmer::{Store, Module, Instance, Value, imports}; -//! use wasmer::Context as WasmerContext; +//! use wasmer::FunctionEnv; //! //! fn main() -> anyhow::Result<()> { //! let module_wat = r#" @@ -53,15 +53,15 @@ //! i32.add)) //! "#; //! -//! let store = Store::default(); -//! let mut ctx = WasmerContext::new(&store, ()); +//! let mut store = Store::default(); +//! let env = FunctionEnv::new(&mut store, ()); //! let module = Module::new(&store, &module_wat)?; //! // The module doesn't import anything, so we create an empty import object. //! let import_object = imports! {}; -//! let instance = Instance::new(&mut ctx, &module, &import_object)?; +//! let instance = Instance::new(&mut store, &module, &import_object)?; //! //! let add_one = instance.exports.get_function("add_one")?; -//! let result = add_one.call(&mut ctx, &[Value::I32(42)])?; +//! let result = add_one.call(&mut store, &[Value::I32(42)])?; //! assert_eq!(result[0], Value::I32(43)); //! //! Ok(()) @@ -151,13 +151,12 @@ //! [`imports`] macro: //! //! ``` -//! # use wasmer::{imports, Function, Memory, MemoryType, Store, Imports}; -//! # use wasmer::ContextMut; -//! # fn imports_example(mut ctx: ContextMut<()>, store: &Store) -> Imports { -//! let memory = Memory::new(&mut ctx, MemoryType::new(1, None, false)).unwrap(); +//! # use wasmer::{imports, Function, FunctionEnv, FunctionEnvMut, Memory, MemoryType, Store, Imports}; +//! # fn imports_example(mut ctx: FunctionEnv<()>, mut store: &mut Store) -> Imports { +//! let memory = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap(); //! imports! { //! "env" => { -//! "my_function" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>| println!("Hello")), +//! "my_function" => Function::new_native(&mut store, &ctx, |_ctx: FunctionEnvMut<()>| println!("Hello")), //! "memory" => memory, //! } //! } @@ -168,12 +167,12 @@ //! from any instance via `instance.exports`: //! //! ``` -//! # use wasmer::{imports, Instance, Function, Memory, TypedFunction, ContextMut}; -//! # fn exports_example(mut ctx: ContextMut<()>, instance: &Instance) -> anyhow::Result<()> { +//! # use wasmer::{imports, Instance, FunctionEnv, Memory, TypedFunction, Store}; +//! # fn exports_example(mut ctx: FunctionEnv<()>, mut store: &mut Store, instance: &Instance) -> anyhow::Result<()> { //! let memory = instance.exports.get_memory("memory")?; //! let memory: &Memory = instance.exports.get("some_other_memory")?; -//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; -//! let result = add.call(&mut ctx, 5, 37)?; +//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut store, "add")?; +//! let result = add.call(&mut store, 5, 37)?; //! assert_eq!(result, 42); //! # Ok(()) //! # } @@ -395,7 +394,7 @@ //! i32.const 1 //! i32.add)) //! "#; -//! let store = Store::default(); +//! let mut store = Store::default(); //! let module = Module::new(&store, &module_wat).unwrap(); //! // The module doesn't import anything, so we create an empty import object. //! let import_object = imports! {}; diff --git a/lib/api/src/sys/context.rs b/lib/api/src/sys/context.rs deleted file mode 100644 index 1168fe8049f..00000000000 --- a/lib/api/src/sys/context.rs +++ /dev/null @@ -1,199 +0,0 @@ -use wasmer_vm::ContextObjects; - -use crate::Store; - -/// We require the context to have a fixed memory address for its lifetime since -/// various bits of the VM have raw pointers that point back to it. Hence we -/// wrap the actual context in a box. -pub(crate) struct ContextInner { - pub(crate) objects: ContextObjects, - pub(crate) store: Store, - pub(crate) data: T, -} - -/// A context containing a set of WebAssembly instances, along with host state. -/// -/// All WebAssembly instances must exist within a context. In the majority of -/// cases each instance will have its own context, but it is possible to have -/// multiple instances in a context when these instances need to interact with -/// each other, for example sharing a memory between instances or calling -/// functions in another instance. -/// -/// The lifetimes of run-time WebAssembly objects, notably [`Instance`], -/// [`Memory`], [`Global`], [`Table`] and [`Function`] is tied to a context: -/// the backing memory for these objects is only freed when the context is -/// freed. -/// -/// The `T` generic parameter allows arbitrary data to be attached to a context. -/// This data can be accessed using the [`Context::data`] and -/// [`Context::data_mut`] methods. Host functions defined using -/// [`Function::new`] and [`Function::new_native`] receive -/// a reference to the context when they are called. -pub struct Context { - pub(crate) inner: Box>, -} - -impl Context { - /// Creates a new context with the given host state. - // TODO: Eliminate the Store type and move its functionality into Engine. - pub fn new(store: &Store, data: T) -> Self { - Self { - inner: Box::new(ContextInner { - objects: Default::default(), - store: store.clone(), - data, - }), - } - } - - /// Returns a reference to the host state in this context. - pub fn data(&self) -> &T { - &self.inner.data - } - - /// Returns a mutable- reference to the host state in this context. - pub fn data_mut(&mut self) -> &mut T { - &mut self.inner.data - } - - /// Drops the context and returns the host state that was stored in it. - pub fn into_data(self) -> T { - self.inner.data - } - - /// Returns a reference to the `Store` of this context. - pub fn store(&self) -> &Store { - &self.inner.store - } - - /// For use with the C API - /// # Safety - /// - /// This is unsafe. - pub unsafe fn transmute_data(&mut self) -> &mut Context { - core::mem::transmute::<&mut Self, &mut Context>(self) - } -} - -/// A temporary handle to a [`Context`]. -pub struct ContextRef<'a, T: 'a> { - inner: &'a ContextInner, -} - -impl<'a, T> ContextRef<'a, T> { - /// Returns a reference to the host state in this context. - pub fn data(&self) -> &'a T { - &self.inner.data - } - - /// Returns a reference to the `Store` of this context. - pub fn store(&self) -> &Store { - &self.inner.store - } - - pub(crate) fn objects(&self) -> &'a ContextObjects { - &self.inner.objects - } -} - -/// A temporary handle to a [`Context`]. -pub struct ContextMut<'a, T: 'a> { - inner: &'a mut ContextInner, -} - -impl ContextMut<'_, T> { - /// Returns a reference to the host state in this context. - pub fn data(&self) -> &T { - &self.inner.data - } - - /// Returns a mutable- reference to the host state in this context. - pub fn data_mut(&mut self) -> &mut T { - &mut self.inner.data - } - - pub(crate) fn objects_mut(&mut self) -> &mut ContextObjects { - &mut self.inner.objects - } - - /// Returns a reference to the `Store` of this context. - pub fn store(&self) -> &Store { - &self.inner.store - } - - pub(crate) fn as_raw(&self) -> *mut ContextInner { - self.inner as *const ContextInner as *mut ContextInner - } - - pub(crate) unsafe fn from_raw(raw: *mut ContextInner) -> Self { - Self { inner: &mut *raw } - } -} - -/// Helper trait for a value that is convertible to a [`ContextRef`]. -pub trait AsContextRef { - /// Host state associated with the [`Context`]. - type Data; - - /// Returns a `ContextRef` pointing to the underlying context. - fn as_context_ref(&self) -> ContextRef<'_, Self::Data>; -} - -/// Helper trait for a value that is convertible to a [`ContextMut`]. -pub trait AsContextMut: AsContextRef { - /// Returns a `ContextMut` pointing to the underlying context. - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data>; -} - -impl AsContextRef for Context { - type Data = T; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - ContextRef { inner: &self.inner } - } -} -impl AsContextMut for Context { - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { - ContextMut { - inner: &mut self.inner, - } - } -} -impl AsContextRef for ContextRef<'_, T> { - type Data = T; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - ContextRef { inner: self.inner } - } -} -impl AsContextRef for ContextMut<'_, T> { - type Data = T; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - ContextRef { inner: self.inner } - } -} -impl AsContextMut for ContextMut<'_, T> { - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { - ContextMut { inner: self.inner } - } -} -impl AsContextRef for &'_ T { - type Data = T::Data; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - T::as_context_ref(*self) - } -} -impl AsContextRef for &'_ mut T { - type Data = T::Data; - - fn as_context_ref(&self) -> ContextRef<'_, Self::Data> { - T::as_context_ref(*self) - } -} -impl AsContextMut for &'_ mut T { - fn as_context_mut(&mut self) -> ContextMut<'_, Self::Data> { - T::as_context_mut(*self) - } -} diff --git a/lib/api/src/sys/exports.rs b/lib/api/src/sys/exports.rs index f9a66d94a19..0a9bce991ba 100644 --- a/lib/api/src/sys/exports.rs +++ b/lib/api/src/sys/exports.rs @@ -1,4 +1,4 @@ -use super::context::AsContextRef; +use super::store::AsStoreRef; use crate::sys::externals::{Extern, Function, Global, Memory, Table}; use crate::sys::native::TypedFunction; use crate::sys::WasmTypeList; @@ -18,16 +18,16 @@ use thiserror::Error; /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError}; -/// # use wasmer::Context as WasmerContext; -/// # let store = Store::default(); -/// # let mut ctx = WasmerContext::new(&store, ()); +/// # use wasmer::FunctionEnv; +/// # let mut store = Store::default(); +/// # let env = FunctionEnv::new(&mut store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (global $one (export "glob") f32 (f32.const 1))) /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; -/// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); +/// # let instance = Instance::new(&mut store, &module, &import_object).unwrap(); /// # /// // This results with an error: `ExportError::IncompatibleType`. /// let export = instance.exports.get_function("glob").unwrap(); @@ -37,13 +37,13 @@ use thiserror::Error; /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError}; -/// # use wasmer::Context as WasmerContext; -/// # let store = Store::default(); -/// # let mut ctx = WasmerContext::new(&store, ()); +/// # use wasmer::FunctionEnv; +/// # let mut store = Store::default(); +/// # let env = FunctionEnv::new(&mut store, ()); /// # let wasm_bytes = wat2wasm("(module)".as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; -/// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); +/// # let instance = Instance::new(&mut store, &module, &import_object).unwrap(); /// # /// // This results with an error: `ExportError::Missing`. /// let export = instance.exports.get_function("unknown").unwrap(); @@ -145,7 +145,7 @@ impl Exports { /// Get an export as a `TypedFunction`. pub fn get_native_function( &self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, name: &str, ) -> Result, ExportError> where @@ -158,7 +158,7 @@ impl Exports { /// Get an export as a `TypedFunction`. pub fn get_typed_function( &self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, name: &str, ) -> Result, ExportError> where diff --git a/lib/api/src/sys/extern_ref.rs b/lib/api/src/sys/extern_ref.rs index 33ff1da3475..c3ca736a710 100644 --- a/lib/api/src/sys/extern_ref.rs +++ b/lib/api/src/sys/extern_ref.rs @@ -1,34 +1,34 @@ use std::any::Any; -use wasmer_vm::{ContextHandle, VMExternObj, VMExternRef}; +use wasmer_vm::{StoreHandle, VMExternObj, VMExternRef}; -use super::context::{AsContextMut, AsContextRef}; +use super::store::{AsStoreMut, AsStoreRef}; #[derive(Debug, Clone)] #[repr(transparent)] /// An opaque reference to some data. This reference can be passed through Wasm. pub struct ExternRef { - handle: ContextHandle, + handle: StoreHandle, } impl ExternRef { /// Make a new extern reference - pub fn new(ctx: &mut impl AsContextMut, value: T) -> Self + pub fn new(ctx: &mut impl AsStoreMut, value: T) -> Self where T: Any + Send + Sync + 'static + Sized, { Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), VMExternObj::new(value)), + handle: StoreHandle::new(ctx.objects_mut(), VMExternObj::new(value)), } } /// Try to downcast to the given value. - pub fn downcast<'a, T>(&self, ctx: &'a impl AsContextRef) -> Option<&'a T> + pub fn downcast<'a, T>(&self, ctx: &'a impl AsStoreRef) -> Option<&'a T> where T: Any + Send + Sync + 'static + Sized, { self.handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .as_ref() .downcast_ref::() } @@ -38,14 +38,11 @@ impl ExternRef { } pub(crate) unsafe fn from_vm_externref( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, vm_externref: VMExternRef, ) -> Self { Self { - handle: ContextHandle::from_internal( - ctx.as_context_mut().objects_mut().id(), - vm_externref.0, - ), + handle: StoreHandle::from_internal(ctx.objects_mut().id(), vm_externref.0), } } @@ -56,7 +53,7 @@ impl ExternRef { /// /// Externref and funcref values are tied to a context and can only be used /// with that context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { + self.handle.store_id() == ctx.as_store_ref().objects().id() } } diff --git a/lib/api/src/sys/externals/function.rs b/lib/api/src/sys/externals/function.rs index d6c6cf8a8c1..7c21ee747e7 100644 --- a/lib/api/src/sys/externals/function.rs +++ b/lib/api/src/sys/externals/function.rs @@ -1,11 +1,11 @@ -use crate::sys::context::{AsContextMut, AsContextRef, ContextInner, ContextMut}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; +use crate::sys::store::{AsStoreMut, AsStoreRef, StoreInner, StoreMut}; use crate::sys::FunctionType; use crate::sys::RuntimeError; use crate::sys::TypedFunction; -use crate::Value; +use crate::{FunctionEnv, FunctionEnvMut, Value}; use inner::StaticFunction; pub use inner::{FromToNativeWasmType, HostFunction, WasmTypeList}; use std::cell::UnsafeCell; @@ -13,10 +13,10 @@ use std::cmp::max; use std::ffi::c_void; use wasmer_types::RawValue; use wasmer_vm::{ - on_host_stack, raise_user_trap, resume_panic, wasmer_call_trampoline, ContextHandle, - InternalContextHandle, MaybeInstanceOwned, VMCallerCheckedAnyfunc, VMContext, - VMDynamicFunctionContext, VMExtern, VMFuncRef, VMFunction, VMFunctionBody, - VMFunctionEnvironment, VMFunctionKind, VMTrampoline, + on_host_stack, raise_user_trap, resume_panic, wasmer_call_trampoline, InternalStoreHandle, + MaybeInstanceOwned, StoreHandle, VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, + VMExtern, VMFuncRef, VMFunction, VMFunctionBody, VMFunctionContext, VMFunctionKind, + VMTrampoline, }; /// A WebAssembly `function` instance. @@ -38,7 +38,7 @@ use wasmer_vm::{ /// [Closures as host functions tracking issue](https://github.com/wasmerio/wasmer/issues/1840) #[derive(Debug, Clone)] pub struct Function { - pub(crate) handle: ContextHandle, + pub(crate) handle: StoreHandle, } impl Function { @@ -50,14 +50,13 @@ impl Function { /// # Examples /// /// ``` - /// # use wasmer::{Function, FunctionType, Type, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::{Function, FunctionEnv, FunctionType, Type, Store, Value}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # /// let signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]); /// - /// let f = Function::new(&mut ctx, &signature, |_ctx, args| { + /// let f = Function::new(&mut store, &env, &signature, |_ctx, args| { /// let sum = args[0].unwrap_i32() + args[1].unwrap_i32(); /// Ok(vec![Value::I32(sum)]) /// }); @@ -66,38 +65,47 @@ impl Function { /// With constant signature: /// /// ``` - /// # use wasmer::{Function, FunctionType, Type, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::{Function, FunctionEnv, FunctionType, Type, Store, Value}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # /// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]); /// - /// let f = Function::new(&mut ctx, I32_I32_TO_I32, |_ctx, args| { + /// let f = Function::new(&mut store, &env, I32_I32_TO_I32, |_ctx, args| { /// let sum = args[0].unwrap_i32() + args[1].unwrap_i32(); /// Ok(vec![Value::I32(sum)]) /// }); /// ``` - pub fn new(ctx: &mut impl AsContextMut, ty: FT, func: F) -> Self + pub fn new( + store: &mut impl AsStoreMut, + env: &FunctionEnv, + ty: FT, + func: F, + ) -> Self where FT: Into, - F: Fn(ContextMut<'_, T>, &[Value]) -> Result, RuntimeError> + F: Fn(FunctionEnvMut, &[Value]) -> Result, RuntimeError> + 'static + Send + Sync, { - let mut ctx = ctx.as_context_mut(); let function_type = ty.into(); let func_ty = function_type.clone(); - let raw_ctx = ctx.as_raw() as *mut u8; + let func_env = env.clone(); + let raw_store = store.as_store_mut().as_raw() as *mut u8; let wrapper = move |values_vec: *mut RawValue| -> Result<(), RuntimeError> { unsafe { - let mut ctx = ContextMut::from_raw(raw_ctx as *mut ContextInner); + let mut store = StoreMut::from_raw(raw_store as *mut StoreInner); let mut args = Vec::with_capacity(func_ty.params().len()); for (i, ty) in func_ty.params().iter().enumerate() { - args.push(Value::from_raw(&mut ctx, *ty, *values_vec.add(i))); + args.push(Value::from_raw(&mut store, *ty, *values_vec.add(i))); } - let returns = func(ctx.as_context_mut(), &args)?; + let store_mut = StoreMut::from_raw(raw_store as *mut StoreInner); + let env = FunctionEnvMut { + store_mut, + func_env: func_env.clone(), + }; + let returns = func(env, &args)?; // We need to dynamically check that the returns // match the expected types, as well as expected length. @@ -110,7 +118,7 @@ impl Function { ))); } for (i, ret) in returns.iter().enumerate() { - *values_vec.add(i) = ret.as_raw(&ctx); + *values_vec.add(i) = ret.as_raw(&store); } } Ok(()) @@ -125,8 +133,11 @@ impl Function { // The engine linker will replace the address with one pointing to a // generated dynamic trampoline. let func_ptr = std::ptr::null() as *const VMFunctionBody; - let type_index = ctx.store().engine().register_signature(&function_type); - let vmctx = VMFunctionEnvironment { + let type_index = store + .as_store_mut() + .engine() + .register_signature(&function_type); + let vmctx = VMFunctionContext { host_env: host_data.as_ref() as *const _ as *mut c_void, }; let call_trampoline = host_data.ctx.call_trampoline_address(); @@ -144,7 +155,7 @@ impl Function { host_data, }; Self { - handle: ContextHandle::new(ctx.objects_mut(), vm_function), + handle: StoreHandle::new(store.as_store_mut().objects_mut(), vm_function), } } @@ -156,33 +167,41 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{ContextMut, Store, Function}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::{Store, Function, FunctionEnv, FunctionEnvMut}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # - /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { + /// fn sum(_ctx: FunctionEnvMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&mut ctx, sum); + /// let f = Function::new_native(&mut store, &env, sum); /// ``` - pub fn new_native(ctx: &mut impl AsContextMut, func: F) -> Self + pub fn new_native( + store: &mut impl AsStoreMut, + env: &FunctionEnv, + func: F, + ) -> Self where F: HostFunction + 'static + Send + Sync, Args: WasmTypeList, Rets: WasmTypeList, { - let mut ctx = ctx.as_context_mut(); + // println!("new native {:p}", &new_ctx); + let host_data = Box::new(StaticFunction { - raw_ctx: ctx.as_raw() as *mut u8, + raw_store: store.as_store_mut().as_raw() as *mut u8, + env: env.clone(), func, }); let function_type = FunctionType::new(Args::wasm_types(), Rets::wasm_types()); let func_ptr = >::function_body_ptr(); - let type_index = ctx.store().engine().register_signature(&function_type); - let vmctx = VMFunctionEnvironment { + let type_index = store + .as_store_mut() + .engine() + .register_signature(&function_type); + let vmctx = VMFunctionContext { host_env: host_data.as_ref() as *const _ as *mut c_void, }; let call_trampoline = >::call_trampoline_address(); @@ -200,7 +219,7 @@ impl Function { host_data, }; Self { - handle: ContextHandle::new(ctx.objects_mut(), vm_function), + handle: StoreHandle::new(store.as_store_mut().objects_mut(), vm_function), } } @@ -209,30 +228,29 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{ContextMut, Function, Store, Type}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # - /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { + /// fn sum(_ctx: FunctionEnvMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&mut ctx, sum); + /// let f = Function::new_native(&mut store, &env, sum); /// - /// assert_eq!(f.ty(&mut ctx).params(), vec![Type::I32, Type::I32]); - /// assert_eq!(f.ty(&mut ctx).results(), vec![Type::I32]); + /// assert_eq!(f.ty(&mut store).params(), vec![Type::I32, Type::I32]); + /// assert_eq!(f.ty(&mut store).results(), vec![Type::I32]); /// ``` - pub fn ty(&self, ctx: &impl AsContextRef) -> FunctionType { + pub fn ty(&self, store: &impl AsStoreRef) -> FunctionType { self.handle - .get(ctx.as_context_ref().objects()) + .get(store.as_store_ref().objects()) .signature .clone() } fn call_wasm( &self, - ctx: &mut impl AsContextMut, + store: &mut impl AsStoreMut, trampoline: VMTrampoline, params: &[Value], results: &mut [Value], @@ -245,7 +263,7 @@ impl Function { .join(", ") }; // TODO: Avoid cloning the signature here, it's expensive. - let signature = self.ty(ctx); + let signature = self.ty(store); if signature.params().len() != params.len() { return Err(RuntimeError::new(format!( "Parameters of type [{}] did not match signature {}", @@ -273,19 +291,19 @@ impl Function { param_types, &signature, ))); } - if !arg.is_from_context(ctx) { + if !arg.is_from_store(store) { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); } - *slot = arg.as_raw(ctx); + *slot = arg.as_raw(store); } // Call the trampoline. - let vm_function = self.handle.get(ctx.as_context_ref().objects()); + let vm_function = self.handle.get(store.as_store_ref().objects()); if let Err(error) = unsafe { wasmer_call_trampoline( - ctx.as_context_ref().store(), + store.as_store_ref().signal_handler(), vm_function.anyfunc.as_ptr().as_ref().vmctx, trampoline, vm_function.anyfunc.as_ptr().as_ref().func_ptr, @@ -298,7 +316,7 @@ impl Function { // Load the return values out of `values_vec`. for (index, &value_type) in signature.results().iter().enumerate() { unsafe { - results[index] = Value::from_raw(ctx, value_type, values_vec[index]); + results[index] = Value::from_raw(store, value_type, values_vec[index]); } } @@ -310,21 +328,20 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{ContextMut, Function, Store, Type}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # - /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { + /// fn sum(_ctx: FunctionEnvMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&mut ctx, sum); + /// let f = Function::new_native(&mut store, &env, sum); /// - /// assert_eq!(f.param_arity(&mut ctx), 2); + /// assert_eq!(f.param_arity(&mut store), 2); /// ``` - pub fn param_arity(&self, ctx: &impl AsContextRef) -> usize { - self.ty(ctx).params().len() + pub fn param_arity(&self, store: &impl AsStoreRef) -> usize { + self.ty(store).params().len() } /// Returns the number of results this function produces. @@ -332,21 +349,20 @@ impl Function { /// # Example /// /// ``` - /// # use wasmer::{ContextMut, Function, Store, Type}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type}; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # - /// fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { + /// fn sum(_ctx: FunctionEnvMut<()>, a: i32, b: i32) -> i32 { /// a + b /// } /// - /// let f = Function::new_native(&mut ctx, sum); + /// let f = Function::new_native(&mut store, &env, sum); /// - /// assert_eq!(f.result_arity(&mut ctx), 1); + /// assert_eq!(f.result_arity(&mut store), 1); /// ``` - pub fn result_arity(&self, ctx: &impl AsContextRef) -> usize { - self.ty(ctx).results().len() + pub fn result_arity(&self, store: &impl AsStoreRef) -> usize { + self.ty(store).results().len() } /// Call the `Function` function. @@ -361,9 +377,9 @@ impl Function { /// /// ``` /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::FunctionEnv; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -374,42 +390,41 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); /// - /// assert_eq!(sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); + /// assert_eq!(sum.call(&mut store, &[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); /// ``` pub fn call( &self, - ctx: &mut impl AsContextMut, + store: &mut impl AsStoreMut, params: &[Value], ) -> Result, RuntimeError> { let trampoline = unsafe { self.handle - .get(ctx.as_context_ref().objects()) + .get(store.as_store_ref().objects()) .anyfunc .as_ptr() .as_ref() .call_trampoline }; - let mut results = vec![Value::null(); self.result_arity(ctx)]; - self.call_wasm(ctx, trampoline, params, &mut results)?; + let mut results = vec![Value::null(); self.result_arity(store)]; + self.call_wasm(store, trampoline, params, &mut results)?; Ok(results.into_boxed_slice()) } - pub(crate) fn vm_funcref(&self, ctx: &impl AsContextRef) -> VMFuncRef { - let vm_function = self.handle.get(ctx.as_context_ref().objects()); + pub(crate) fn vm_funcref(&self, store: &impl AsStoreRef) -> VMFuncRef { + let vm_function = self.handle.get(store.as_store_ref().objects()); if vm_function.kind == VMFunctionKind::Dynamic { panic!("dynamic functions cannot be used in tables or as funcrefs"); } VMFuncRef(vm_function.anyfunc.as_ptr()) } - pub(crate) unsafe fn from_vm_funcref(ctx: &mut impl AsContextMut, funcref: VMFuncRef) -> Self { - let signature = ctx - .as_context_mut() - .store() + pub(crate) unsafe fn from_vm_funcref(store: &mut impl AsStoreMut, funcref: VMFuncRef) -> Self { + let signature = store + .as_store_ref() .engine() .lookup_signature(funcref.0.as_ref().type_index) .expect("Signature not found in store"); @@ -422,7 +437,7 @@ impl Function { host_data: Box::new(()), }; Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), vm_function), + handle: StoreHandle::new(store.as_store_mut().objects_mut(), vm_function), } } @@ -433,9 +448,9 @@ impl Function { /// /// ``` /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::FunctionEnv; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -446,12 +461,12 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); - /// let sum_native: TypedFunction<(i32, i32), i32> = sum.native(&mut ctx).unwrap(); + /// let sum_native: TypedFunction<(i32, i32), i32> = sum.native(&mut store).unwrap(); /// - /// assert_eq!(sum_native.call(&mut ctx, 1, 2).unwrap(), 3); + /// assert_eq!(sum_native.call(&mut store, 1, 2).unwrap(), 3); /// ``` /// /// # Errors @@ -461,9 +476,9 @@ impl Function { /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::FunctionEnv; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -474,12 +489,12 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); /// /// // This results in an error: `RuntimeError` - /// let sum_native : TypedFunction<(i64, i64), i32> = sum.native(&mut ctx).unwrap(); + /// let sum_native : TypedFunction<(i64, i64), i32> = sum.native(&mut store).unwrap(); /// ``` /// /// If the `Rets` generic parameter does not match the exported function @@ -487,9 +502,9 @@ impl Function { /// /// ```should_panic /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::FunctionEnv; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # let wasm_bytes = wat2wasm(r#" /// # (module /// # (func (export "sum") (param $x i32) (param $y i32) (result i32) @@ -500,22 +515,22 @@ impl Function { /// # "#.as_bytes()).unwrap(); /// # let module = Module::new(&store, wasm_bytes).unwrap(); /// # let import_object = imports! {}; - /// # let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap(); /// # /// let sum = instance.exports.get_function("sum").unwrap(); /// /// // This results in an error: `RuntimeError` - /// let sum_native: TypedFunction<(i32, i32), i64> = sum.native(&mut ctx).unwrap(); + /// let sum_native: TypedFunction<(i32, i32), i64> = sum.native(&mut store).unwrap(); /// ``` pub fn native( &self, - ctx: &impl AsContextRef, + store: &impl AsStoreRef, ) -> Result, RuntimeError> where Args: WasmTypeList, Rets: WasmTypeList, { - let vm_function = self.handle.get(ctx.as_context_ref().objects()); + let vm_function = self.handle.get(store.as_store_ref().objects()); // type check { @@ -549,19 +564,19 @@ impl Function { } pub(crate) fn from_vm_extern( - ctx: &mut impl AsContextMut, - internal: InternalContextHandle, + store: &mut impl AsStoreMut, + internal: InternalStoreHandle, ) -> Self { Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(store.as_store_ref().objects().id(), internal) }, } } - /// Checks whether this `Function` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + /// Checks whether this `Function` can be used with the given store. + pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool { + self.handle.store_id() == store.as_store_ref().objects().id() } pub(crate) fn to_vm_extern(&self) -> VMExtern { @@ -590,10 +605,11 @@ where // This function wraps our func, to make it compatible with the // reverse trampoline signature unsafe extern "C" fn func_wrapper( - this: &VMDynamicFunctionContext, + this: &mut VMDynamicFunctionContext, values_vec: *mut RawValue, ) { use std::panic::{self, AssertUnwindSafe}; + let result = on_host_stack(|| panic::catch_unwind(AssertUnwindSafe(|| (this.ctx.func)(values_vec)))); @@ -633,12 +649,12 @@ mod inner { use std::panic::{self, AssertUnwindSafe}; use wasmer_vm::{on_host_stack, VMContext, VMTrampoline}; + use crate::sys::function_env::FunctionEnvMut; use wasmer_types::{NativeWasmType, RawValue, Type}; use wasmer_vm::{raise_user_trap, resume_panic, VMFunctionBody}; - use crate::sys::context::{ContextInner, ContextMut}; use crate::sys::NativeWasmTypeInto; - use crate::{AsContextMut, AsContextRef, ExternRef, Function}; + use crate::{AsStoreMut, AsStoreRef, ExternRef, Function, FunctionEnv, StoreMut}; /// A trait to convert a Rust value to a `WasmNativeType` value, /// or to convert `WasmNativeType` value to a Rust value. @@ -674,11 +690,11 @@ mod inner { /// `Self::Native` type. fn to_native(self) -> Self::Native; - /// Returns whether the given value is from the given context. + /// Returns whether the given value is from the given store. /// /// This always returns true for primitive types that can be used with /// any context. - fn is_from_context(&self, _ctx: &impl AsContextRef) -> bool { + fn is_from_store(&self, _ctx: &impl AsStoreRef) -> bool { true } } @@ -750,8 +766,8 @@ mod inner { fn from_native(n: Self::Native) -> Self { n } - fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.as_ref().map_or(true, |e| e.is_from_context(ctx)) + fn is_from_store(&self, store: &impl AsStoreRef) -> bool { + self.as_ref().map_or(true, |e| e.is_from_store(store)) } } @@ -764,8 +780,8 @@ mod inner { fn from_native(n: Self::Native) -> Self { n } - fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.as_ref().map_or(true, |f| f.is_from_context(ctx)) + fn is_from_store(&self, store: &impl AsStoreRef) -> bool { + self.as_ref().map_or(true, |f| f.is_from_store(store)) } } @@ -812,7 +828,7 @@ mod inner { /// Constructs `Self` based on an array of values. /// /// # Safety - unsafe fn from_array(ctx: &mut impl AsContextMut, array: Self::Array) -> Self; + unsafe fn from_array(ctx: &mut impl AsStoreMut, array: Self::Array) -> Self; /// Constructs `Self` based on a slice of values. /// @@ -823,7 +839,7 @@ mod inner { /// /// # Safety unsafe fn from_slice( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, slice: &[RawValue], ) -> Result; @@ -831,7 +847,7 @@ mod inner { /// (list) of values. /// /// # Safety - unsafe fn into_array(self, ctx: &mut impl AsContextMut) -> Self::Array; + unsafe fn into_array(self, store: &mut impl AsStoreMut) -> Self::Array; /// Allocates and return an empty array of type `Array` that /// will hold a tuple (list) of values, usually to hold the @@ -842,13 +858,13 @@ mod inner { /// `CStruct`. /// /// # Safety - unsafe fn from_c_struct(ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self; + unsafe fn from_c_struct(store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self; /// Builds and returns a C struct of type `CStruct` from a /// tuple (list) of values. /// /// # Safety - unsafe fn into_c_struct(self, ctx: &mut impl AsContextMut) -> Self::CStruct; + unsafe fn into_c_struct(self, store: &mut impl AsStoreMut) -> Self::CStruct; /// Writes the contents of a C struct to an array of `RawValue`. /// @@ -963,8 +979,9 @@ mod inner { /// Represents a low-level Wasm static host function. See /// `super::Function::new_native` to learn more. - pub(crate) struct StaticFunction { - pub(crate) raw_ctx: *mut u8, + pub(crate) struct StaticFunction { + pub(crate) raw_store: *mut u8, + pub(crate) env: FunctionEnv, pub(crate) func: F, } @@ -996,7 +1013,7 @@ mod inner { #[allow(unused_mut)] #[allow(clippy::unused_unit)] #[allow(clippy::missing_safety_doc)] - unsafe fn from_array(mut _ctx: &mut impl AsContextMut, array: Self::Array) -> Self { + unsafe fn from_array(mut _store: &mut impl AsStoreMut, array: Self::Array) -> Self { // Unpack items of the array. #[allow(non_snake_case)] let [ $( $x ),* ] = array; @@ -1004,19 +1021,19 @@ mod inner { // Build the tuple. ( $( - FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_ctx, $x)) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_raw(_store, $x)) ),* ) } #[allow(clippy::missing_safety_doc)] - unsafe fn from_slice(ctx: &mut impl AsContextMut, slice: &[RawValue]) -> Result { - Ok(Self::from_array(ctx, slice.try_into()?)) + unsafe fn from_slice(store: &mut impl AsStoreMut, slice: &[RawValue]) -> Result { + Ok(Self::from_array(store, slice.try_into()?)) } #[allow(unused_mut)] #[allow(clippy::missing_safety_doc)] - unsafe fn into_array(self, mut _ctx: &mut impl AsContextMut) -> Self::Array { + unsafe fn into_array(self, mut _store: &mut impl AsStoreMut) -> Self::Array { // Unpack items of the tuple. #[allow(non_snake_case)] let ( $( $x ),* ) = self; @@ -1024,7 +1041,7 @@ mod inner { // Build the array. [ $( - FromToNativeWasmType::to_native($x).into_raw(_ctx) + FromToNativeWasmType::to_native($x).into_raw(_store) ),* ] } @@ -1037,28 +1054,28 @@ mod inner { #[allow(unused_mut)] #[allow(clippy::unused_unit)] #[allow(clippy::missing_safety_doc)] - unsafe fn from_c_struct(mut _ctx: &mut impl AsContextMut, c_struct: Self::CStruct) -> Self { + unsafe fn from_c_struct(mut _store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self { // Unpack items of the C structure. #[allow(non_snake_case)] let $c_struct_name( $( $x ),* ) = c_struct; ( $( - FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_ctx, $x)) + FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(_store, $x)) ),* ) } #[allow(unused_parens, non_snake_case, unused_mut)] #[allow(clippy::missing_safety_doc)] - unsafe fn into_c_struct(self, mut _ctx: &mut impl AsContextMut) -> Self::CStruct { + unsafe fn into_c_struct(self, mut _store: &mut impl AsStoreMut) -> Self::CStruct { // Unpack items of the tuple. let ( $( $x ),* ) = self; // Build the C structure. $c_struct_name( $( - FromToNativeWasmType::to_native($x).into_abi(_ctx) + FromToNativeWasmType::to_native($x).into_abi(_store) ),* ) } @@ -1086,7 +1103,7 @@ mod inner { // Implement `HostFunction` for a function that has the same arity than the tuple. #[allow(unused_parens)] - impl< $( $x, )* Rets, RetsAsResult, T, Func > + impl< $( $x, )* Rets, RetsAsResult, T: Send + 'static, Func > HostFunction for Func @@ -1094,33 +1111,41 @@ mod inner { $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, + Func: Fn(FunctionEnvMut, $( $x , )*) -> RetsAsResult + 'static, { #[allow(non_snake_case)] fn function_body_ptr() -> *const VMFunctionBody { /// This is a function that wraps the real host /// function. Its address will be used inside the /// runtime. - unsafe extern "C" fn func_wrapper( env: &StaticFunction, $( $x: <$x::Native as NativeWasmType>::Abi, )* ) -> Rets::CStruct + unsafe extern "C" fn func_wrapper( env: &StaticFunction, $( $x: <$x::Native as NativeWasmType>::Abi, )* ) -> Rets::CStruct where $( $x: FromToNativeWasmType, )* Rets: WasmTypeList, RetsAsResult: IntoResult, - Func: Fn(ContextMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static, + Func: Fn(FunctionEnvMut, $( $x , )*) -> RetsAsResult + 'static, { - let mut ctx = ContextMut::from_raw(env.raw_ctx as *mut ContextInner); - + // println!("func wrapper"); + let mut store = StoreMut::from_raw(env.raw_store as *mut _); let result = on_host_stack(|| { + // println!("func wrapper1"); panic::catch_unwind(AssertUnwindSafe(|| { $( - let $x = FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(&mut ctx, $x)); + let $x = FromToNativeWasmType::from_native(NativeWasmTypeInto::from_abi(&mut store, $x)); )* - (env.func)(ctx.as_context_mut(), $($x),* ).into_result() + // println!("func wrapper2 {:p}", *env.raw_ctx); + let store_mut = StoreMut::from_raw(env.raw_store as *mut _); + let f_env = FunctionEnvMut { + store_mut, + func_env: env.env.clone(), + }; + // println!("func wrapper3"); + (env.func)(f_env, $($x),* ).into_result() })) }); match result { - Ok(Ok(result)) => return result.into_c_struct(&mut ctx), + Ok(Ok(result)) => return result.into_c_struct(&mut store), Ok(Err(trap)) => raise_user_trap(Box::new(trap)), Err(panic) => resume_panic(panic) , } @@ -1212,18 +1237,18 @@ mod inner { type CStruct = Self; type Array = [RawValue; 0]; - unsafe fn from_array(_: &mut impl AsContextMut, _: Self::Array) -> Self { + unsafe fn from_array(_: &mut impl AsStoreMut, _: Self::Array) -> Self { unreachable!() } unsafe fn from_slice( - _: &mut impl AsContextMut, + _: &mut impl AsStoreMut, _: &[RawValue], ) -> Result { unreachable!() } - unsafe fn into_array(self, _: &mut impl AsContextMut) -> Self::Array { + unsafe fn into_array(self, _: &mut impl AsStoreMut) -> Self::Array { [] } @@ -1231,11 +1256,11 @@ mod inner { [] } - unsafe fn from_c_struct(_: &mut impl AsContextMut, self_: Self::CStruct) -> Self { + unsafe fn from_c_struct(_: &mut impl AsStoreMut, self_: Self::CStruct) -> Self { self_ } - unsafe fn into_c_struct(self, _: &mut impl AsContextMut) -> Self::CStruct { + unsafe fn into_c_struct(self, _: &mut impl AsStoreMut) -> Self::CStruct { self } @@ -1249,14 +1274,12 @@ mod inner { #[cfg(test)] mod test_wasm_type_list { use super::*; - use crate::Context as WasmerContext; - use crate::Store; use wasmer_types::Type; /* #[test] fn test_from_array() { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); assert_eq!(<()>::from_array(&mut ctx, []), ()); assert_eq!(::from_array(&mut ctx, [RawValue{i32: 1}]), (1i32)); assert_eq!(<(i32, i64)>::from_array(&mut ctx, [RawValue{i32:1}, RawValue{i64:2}]), (1i32, 2i64)); @@ -1273,8 +1296,8 @@ mod inner { #[test] fn test_into_array() { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); assert_eq!(().into_array(&mut ctx), [0i128; 0]); assert_eq!((1i32).into_array(&mut ctx), [1i32]); assert_eq!((1i32, 2i64).into_array(&mut ctx), [RawValue{i32: 1}, RawValue{i64: 2}]); @@ -1293,8 +1316,8 @@ mod inner { /* #[test] fn test_from_c_struct() { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); assert_eq!(<()>::from_c_struct(&mut ctx, S0()), ()); assert_eq!(::from_c_struct(&mut ctx, S1(1)), (1i32)); assert_eq!(<(i32, i64)>::from_c_struct(&mut ctx, S2(1, 2)), (1i32, 2i64)); @@ -1331,7 +1354,7 @@ mod inner { mod test_function { use super::*; use crate::Store; - use crate::Context as WasmerContext; + use crate::FunctionEnv; use wasmer_types::Type; fn func() {} @@ -1354,15 +1377,15 @@ mod inner { #[test] fn test_function_types() { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); use wasmer_types::FunctionType; assert_eq!( - StaticFunction::new(func).ty(&mut ctx), + StaticFunction::new(func).ty(&mut store), FunctionType::new(vec![], vec![]) ); assert_eq!( - StaticFunction::new(func__i32).ty(&mut ctx), + StaticFunction::new(func__i32).ty(&mut store), FunctionType::new(vec![], vec![Type::I32]) ); assert_eq!( diff --git a/lib/api/src/sys/externals/global.rs b/lib/api/src/sys/externals/global.rs index 627325f4d16..108d256d08e 100644 --- a/lib/api/src/sys/externals/global.rs +++ b/lib/api/src/sys/externals/global.rs @@ -1,11 +1,11 @@ -use crate::sys::context::{AsContextMut, AsContextRef}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; +use crate::sys::store::{AsStoreMut, AsStoreRef}; use crate::sys::value::Value; use crate::sys::GlobalType; use crate::sys::Mutability; use crate::sys::RuntimeError; -use wasmer_vm::{ContextHandle, InternalContextHandle, VMExtern, VMGlobal}; +use wasmer_vm::{InternalStoreHandle, StoreHandle, VMExtern, VMGlobal}; /// A WebAssembly `global` instance. /// @@ -15,7 +15,7 @@ use wasmer_vm::{ContextHandle, InternalContextHandle, VMExtern, VMGlobal}; /// Spec: #[derive(Debug, Clone)] pub struct Global { - handle: ContextHandle, + handle: StoreHandle, } impl Global { @@ -25,16 +25,14 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let g = Global::new(&mut ctx, Value::I32(1)); + /// let g = Global::new(&mut store, Value::I32(1)); /// - /// assert_eq!(g.get(&mut ctx), Value::I32(1)); - /// assert_eq!(g.ty(&mut ctx).mutability, Mutability::Const); + /// assert_eq!(g.get(&mut store), Value::I32(1)); + /// assert_eq!(g.ty(&mut store).mutability, Mutability::Const); /// ``` - pub fn new(ctx: &mut impl AsContextMut, val: Value) -> Self { + pub fn new(ctx: &mut impl AsStoreMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Const).unwrap() } @@ -44,26 +42,24 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let g = Global::new_mut(&mut ctx, Value::I32(1)); + /// let g = Global::new_mut(&mut store, Value::I32(1)); /// - /// assert_eq!(g.get(&mut ctx), Value::I32(1)); - /// assert_eq!(g.ty(&mut ctx).mutability, Mutability::Var); + /// assert_eq!(g.get(&mut store), Value::I32(1)); + /// assert_eq!(g.ty(&mut store).mutability, Mutability::Var); /// ``` - pub fn new_mut(ctx: &mut impl AsContextMut, val: Value) -> Self { + pub fn new_mut(ctx: &mut impl AsStoreMut, val: Value) -> Self { Self::from_value(ctx, val, Mutability::Var).unwrap() } /// Create a `Global` with the initial value [`Val`] and the provided [`Mutability`]. fn from_value( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, val: Value, mutability: Mutability, ) -> Result { - if !val.is_from_context(ctx) { + if !val.is_from_store(ctx) { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); @@ -77,7 +73,7 @@ impl Global { } Ok(Self { - handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), global), + handle: StoreHandle::new(ctx.objects_mut(), global), }) } @@ -87,18 +83,16 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Mutability, Store, Type, Value, GlobalType}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let c = Global::new(&mut ctx, Value::I32(1)); - /// let v = Global::new_mut(&mut ctx, Value::I64(1)); + /// let c = Global::new(&mut store, Value::I32(1)); + /// let v = Global::new_mut(&mut store, Value::I64(1)); /// - /// assert_eq!(c.ty(&mut ctx), GlobalType::new(Type::I32, Mutability::Const)); - /// assert_eq!(v.ty(&mut ctx), GlobalType::new(Type::I64, Mutability::Var)); + /// assert_eq!(c.ty(&mut store), GlobalType::new(Type::I32, Mutability::Const)); + /// assert_eq!(v.ty(&mut store), GlobalType::new(Type::I64, Mutability::Var)); /// ``` - pub fn ty(&self, ctx: &impl AsContextRef) -> GlobalType { - *self.handle.get(ctx.as_context_ref().objects()).ty() + pub fn ty(&self, ctx: &impl AsStoreRef) -> GlobalType { + *self.handle.get(ctx.as_store_ref().objects()).ty() } /// Retrieves the current value [`Val`] that the Global has. @@ -107,23 +101,21 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let g = Global::new(&mut ctx, Value::I32(1)); + /// let g = Global::new(&mut store, Value::I32(1)); /// - /// assert_eq!(g.get(&mut ctx), Value::I32(1)); + /// assert_eq!(g.get(&mut store), Value::I32(1)); /// ``` - pub fn get(&self, ctx: &mut impl AsContextMut) -> Value { + pub fn get(&self, ctx: &mut impl AsStoreMut) -> Value { unsafe { let raw = self .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .vmglobal() .as_ref() .val; - let ty = self.handle.get(ctx.as_context_ref().objects()).ty().ty; + let ty = self.handle.get(ctx.as_store_ref().objects()).ty().ty; Value::from_raw(ctx, ty, raw) } } @@ -134,17 +126,15 @@ impl Global { /// /// ``` /// # use wasmer::{Global, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let g = Global::new_mut(&mut ctx, Value::I32(1)); + /// let g = Global::new_mut(&mut store, Value::I32(1)); /// - /// assert_eq!(g.get(&mut ctx), Value::I32(1)); + /// assert_eq!(g.get(&mut store), Value::I32(1)); /// - /// g.set(&mut ctx, Value::I32(2)); + /// g.set(&mut store, Value::I32(2)); /// - /// assert_eq!(g.get(&mut ctx), Value::I32(2)); + /// assert_eq!(g.get(&mut store), Value::I32(2)); /// ``` /// /// # Errors @@ -153,30 +143,26 @@ impl Global { /// /// ```should_panic /// # use wasmer::{Global, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let g = Global::new(&mut ctx, Value::I32(1)); + /// let g = Global::new(&mut store, Value::I32(1)); /// - /// g.set(&mut ctx, Value::I32(2)).unwrap(); + /// g.set(&mut store, Value::I32(2)).unwrap(); /// ``` /// /// Trying to set a value of a incompatible type will raise an error: /// /// ```should_panic /// # use wasmer::{Global, Store, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let g = Global::new(&mut ctx, Value::I32(1)); + /// let g = Global::new(&mut store, Value::I32(1)); /// /// // This results in an error: `RuntimeError`. - /// g.set(&mut ctx, Value::I64(2)).unwrap(); + /// g.set(&mut store, Value::I64(2)).unwrap(); /// ``` - pub fn set(&self, ctx: &mut impl AsContextMut, val: Value) -> Result<(), RuntimeError> { - if !val.is_from_context(ctx) { + pub fn set(&self, ctx: &mut impl AsStoreMut, val: Value) -> Result<(), RuntimeError> { + if !val.is_from_store(ctx) { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); @@ -193,7 +179,7 @@ impl Global { } unsafe { self.handle - .get_mut(ctx.as_context_mut().objects_mut()) + .get_mut(ctx.objects_mut()) .vmglobal() .as_mut() .val = val.as_raw(ctx); @@ -202,19 +188,19 @@ impl Global { } pub(crate) fn from_vm_extern( - ctx: &mut impl AsContextMut, - internal: InternalContextHandle, + ctx: &mut impl AsStoreMut, + internal: InternalStoreHandle, ) -> Self { Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(ctx.as_store_ref().objects().id(), internal) }, } } /// Checks whether this `Global` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { + self.handle.store_id() == ctx.as_store_ref().objects().id() } pub(crate) fn to_vm_extern(&self) -> VMExtern { diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 136e7620436..45b093c5070 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -1,6 +1,6 @@ -use crate::sys::context::{AsContextMut, AsContextRef}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; +use crate::sys::store::{AsStoreMut, AsStoreRef}; use crate::sys::MemoryType; use crate::MemoryAccessError; use std::convert::TryInto; @@ -9,9 +9,7 @@ use std::mem; use std::mem::MaybeUninit; use std::slice; use wasmer_types::Pages; -use wasmer_vm::{ - ContextHandle, ContextObjects, InternalContextHandle, MemoryError, VMExtern, VMMemory, -}; +use wasmer_vm::{InternalStoreHandle, MemoryError, StoreHandle, StoreObjects, VMExtern, VMMemory}; /// A WebAssembly `memory` instance. /// @@ -29,7 +27,7 @@ use wasmer_vm::{ /// Spec: #[derive(Debug, Clone)] pub struct Memory { - handle: ContextHandle, + handle: StoreHandle, } impl Memory { @@ -42,20 +40,18 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let m = Memory::new(&mut ctx, MemoryType::new(1, None, false)).unwrap(); + /// let m = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap(); /// ``` - pub fn new(ctx: &mut impl AsContextMut, ty: MemoryType) -> Result { - let mut ctx = ctx.as_context_mut(); - let tunables = ctx.store().tunables(); + pub fn new(ctx: &mut impl AsStoreMut, ty: MemoryType) -> Result { + let mut ctx = ctx.as_store_mut(); + let tunables = ctx.tunables(); let style = tunables.memory_style(&ty); let memory = tunables.create_host_memory(&ty, &style)?; Ok(Self { - handle: ContextHandle::new(ctx.objects_mut(), memory), + handle: StoreHandle::new(ctx.objects_mut(), memory), }) } @@ -65,17 +61,15 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # /// let mt = MemoryType::new(1, None, false); - /// let m = Memory::new(&mut ctx, mt).unwrap(); + /// let m = Memory::new(&mut store, mt).unwrap(); /// - /// assert_eq!(m.ty(&mut ctx), mt); + /// assert_eq!(m.ty(&mut store), mt); /// ``` - pub fn ty(&self, ctx: &impl AsContextRef) -> MemoryType { - self.handle.get(ctx.as_context_ref().objects()).ty() + pub fn ty(&self, ctx: &impl AsStoreRef) -> MemoryType { + self.handle.get(ctx.as_store_ref().objects()).ty() } /// Returns the pointer to the raw bytes of the `Memory`. @@ -83,12 +77,12 @@ impl Memory { // This used by wasmer-emscripten and wasmer-c-api, but should be treated // as deprecated and not used in future code. #[doc(hidden)] - pub fn data_ptr(&self, ctx: &impl AsContextRef) -> *mut u8 { + pub fn data_ptr(&self, ctx: &impl AsStoreRef) -> *mut u8 { self.buffer(ctx).base } /// Returns the size (in bytes) of the `Memory`. - pub fn data_size(&self, ctx: &impl AsContextRef) -> u64 { + pub fn data_size(&self, ctx: &impl AsStoreRef) -> u64 { self.buffer(ctx).len.try_into().unwrap() } @@ -98,16 +92,14 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let m = Memory::new(&mut ctx, MemoryType::new(1, None, false)).unwrap(); + /// let m = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap(); /// - /// assert_eq!(m.size(&mut ctx), Pages(1)); + /// assert_eq!(m.size(&mut store), Pages(1)); /// ``` - pub fn size(&self, ctx: &impl AsContextRef) -> Pages { - self.handle.get(ctx.as_context_ref().objects()).size() + pub fn size(&self, ctx: &impl AsStoreRef) -> Pages { + self.handle.get(ctx.as_store_ref().objects()).size() } /// Grow memory by the specified amount of WebAssembly [`Pages`] and return @@ -117,15 +109,13 @@ impl Memory { /// /// ``` /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # let mut store = Store::default(); /// # - /// let m = Memory::new(&mut ctx, MemoryType::new(1, Some(3), false)).unwrap(); - /// let p = m.grow(&mut ctx, 2).unwrap(); + /// let m = Memory::new(&mut store, MemoryType::new(1, Some(3), false)).unwrap(); + /// let p = m.grow(&mut store, 2).unwrap(); /// /// assert_eq!(p, Pages(1)); - /// assert_eq!(m.size(&mut ctx), Pages(3)); + /// assert_eq!(m.size(&mut store), Pages(3)); /// ``` /// /// # Errors @@ -135,26 +125,24 @@ impl Memory { /// /// ```should_panic /// # use wasmer::{Memory, MemoryType, Pages, Store, Type, Value, WASM_MAX_PAGES}; - /// # use wasmer::Context as WasmerContext; - /// # let store = Store::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); + /// # use wasmer::FunctionEnv; + /// # let mut store = Store::default(); + /// # let env = FunctionEnv::new(&mut store, ()); /// # - /// let m = Memory::new(&mut ctx, MemoryType::new(1, Some(1), false)).unwrap(); + /// let m = Memory::new(&mut store, MemoryType::new(1, Some(1), false)).unwrap(); /// /// // This results in an error: `MemoryError::CouldNotGrow`. - /// let s = m.grow(&mut ctx, 1).unwrap(); + /// let s = m.grow(&mut store, 1).unwrap(); /// ``` pub fn grow( &self, - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, delta: IntoPages, ) -> Result where IntoPages: Into, { - self.handle - .get_mut(ctx.as_context_mut().objects_mut()) - .grow(delta.into()) + self.handle.get_mut(ctx.objects_mut()).grow(delta.into()) } /// Safely reads bytes from the memory at the given offset. @@ -166,7 +154,7 @@ impl Memory { /// concurrent writes. pub fn read( &self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, offset: u64, buf: &mut [u8], ) -> Result<(), MemoryAccessError> { @@ -185,7 +173,7 @@ impl Memory { /// concurrent writes. pub fn read_uninit<'a>( &self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, offset: u64, buf: &'a mut [MaybeUninit], ) -> Result<&'a mut [u8], MemoryAccessError> { @@ -201,15 +189,15 @@ impl Memory { /// concurrent reads/writes. pub fn write( &self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, offset: u64, data: &[u8], ) -> Result<(), MemoryAccessError> { self.buffer(ctx).write(offset, data) } - pub(crate) fn buffer<'a>(&'a self, ctx: &'a impl AsContextRef) -> MemoryBuffer<'a> { - let definition = self.handle.get(ctx.as_context_ref().objects()).vmmemory(); + pub(crate) fn buffer<'a>(&'a self, ctx: &'a impl AsStoreRef) -> MemoryBuffer<'a> { + let definition = self.handle.get(ctx.as_store_ref().objects()).vmmemory(); let def = unsafe { definition.as_ref() }; MemoryBuffer { base: def.base, @@ -219,19 +207,19 @@ impl Memory { } pub(crate) fn from_vm_extern( - ctx: &impl AsContextRef, - internal: InternalContextHandle, + ctx: &impl AsStoreRef, + internal: InternalStoreHandle, ) -> Self { Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(ctx.as_store_ref().objects().id(), internal) }, } } /// Checks whether this `Memory` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { + self.handle.store_id() == ctx.as_store_ref().objects().id() } pub(crate) fn to_vm_extern(&self) -> VMExtern { @@ -261,7 +249,7 @@ impl<'a> Exportable<'a> for Memory { pub(crate) struct MemoryBuffer<'a> { base: *mut u8, len: usize, - marker: PhantomData<(&'a Memory, &'a ContextObjects)>, + marker: PhantomData<(&'a Memory, &'a StoreObjects)>, } impl<'a> MemoryBuffer<'a> { diff --git a/lib/api/src/sys/externals/mod.rs b/lib/api/src/sys/externals/mod.rs index 7625f7ca206..da4fff433b7 100644 --- a/lib/api/src/sys/externals/mod.rs +++ b/lib/api/src/sys/externals/mod.rs @@ -14,7 +14,7 @@ use crate::sys::ExternType; use std::fmt; use wasmer_vm::VMExtern; -use super::context::{AsContextMut, AsContextRef}; +use super::store::{AsStoreMut, AsStoreRef}; /// An `Extern` is the runtime representation of an entity that /// can be imported or exported. @@ -34,7 +34,7 @@ pub enum Extern { impl Extern { /// Return the underlying type of the inner `Extern`. - pub fn ty(&self, ctx: &impl AsContextRef) -> ExternType { + pub fn ty(&self, ctx: &impl AsStoreRef) -> ExternType { match self { Self::Function(ft) => ExternType::Function(ft.ty(ctx)), Self::Memory(ft) => ExternType::Memory(ft.ty(ctx)), @@ -44,7 +44,7 @@ impl Extern { } /// Create an `Extern` from an `wasmer_engine::Export`. - pub fn from_vm_extern(ctx: &mut impl AsContextMut, vm_extern: VMExtern) -> Self { + pub fn from_vm_extern(ctx: &mut impl AsStoreMut, vm_extern: VMExtern) -> Self { match vm_extern { VMExtern::Function(f) => Self::Function(Function::from_vm_extern(ctx, f)), VMExtern::Memory(m) => Self::Memory(Memory::from_vm_extern(ctx, m)), @@ -54,12 +54,12 @@ impl Extern { } /// Checks whether this `Extern` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { match self { - Self::Function(f) => f.is_from_context(ctx), - Self::Global(g) => g.is_from_context(ctx), - Self::Memory(m) => m.is_from_context(ctx), - Self::Table(t) => t.is_from_context(ctx), + Self::Function(f) => f.is_from_store(ctx), + Self::Global(g) => g.is_from_store(ctx), + Self::Memory(m) => m.is_from_store(ctx), + Self::Table(t) => t.is_from_store(ctx), } } diff --git a/lib/api/src/sys/externals/table.rs b/lib/api/src/sys/externals/table.rs index 9e2862b9bd5..7f6a24cb36d 100644 --- a/lib/api/src/sys/externals/table.rs +++ b/lib/api/src/sys/externals/table.rs @@ -1,10 +1,10 @@ -use crate::sys::context::{AsContextMut, AsContextRef}; use crate::sys::exports::{ExportError, Exportable}; use crate::sys::externals::Extern; +use crate::sys::store::{AsStoreMut, AsStoreRef}; use crate::sys::RuntimeError; use crate::sys::TableType; use crate::{ExternRef, Function, Value}; -use wasmer_vm::{ContextHandle, InternalContextHandle, TableElement, VMExtern, VMTable}; +use wasmer_vm::{InternalStoreHandle, StoreHandle, TableElement, VMExtern, VMTable}; /// A WebAssembly `table` instance. /// @@ -17,7 +17,7 @@ use wasmer_vm::{ContextHandle, InternalContextHandle, TableElement, VMExtern, VM /// Spec: #[derive(Debug, Clone)] pub struct Table { - handle: ContextHandle, + handle: StoreHandle, } fn set_table_item( @@ -29,10 +29,10 @@ fn set_table_item( } fn value_to_table_element( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, val: Value, ) -> Result { - if !val.is_from_context(ctx) { + if !val.is_from_store(ctx) { return Err(RuntimeError::new("cannot pass Value across contexts")); } Ok(match val { @@ -46,7 +46,7 @@ fn value_to_table_element( }) } -fn value_from_table_element(ctx: &mut impl AsContextMut, item: wasmer_vm::TableElement) -> Value { +fn value_from_table_element(ctx: &mut impl AsStoreMut, item: wasmer_vm::TableElement) -> Value { match item { wasmer_vm::TableElement::FuncRef(funcref) => { Value::FuncRef(funcref.map(|f| unsafe { Function::from_vm_funcref(ctx, f) })) @@ -65,13 +65,13 @@ impl Table { /// This function will construct the `Table` using the store /// [`BaseTunables`][crate::sys::BaseTunables]. pub fn new( - ctx: &mut impl AsContextMut, + mut ctx: &mut impl AsStoreMut, ty: TableType, init: Value, ) -> Result { - let mut ctx = ctx.as_context_mut(); let item = value_to_table_element(&mut ctx, init)?; - let tunables = ctx.store().tunables(); + let mut ctx = ctx.as_store_mut(); + let tunables = ctx.tunables(); let style = tunables.table_style(&ty); let mut table = tunables .create_host_table(&ty, &style) @@ -83,39 +83,35 @@ impl Table { } Ok(Self { - handle: ContextHandle::new(ctx.objects_mut(), table), + handle: StoreHandle::new(ctx.objects_mut(), table), }) } /// Returns the [`TableType`] of the `Table`. - pub fn ty(&self, ctx: &impl AsContextRef) -> TableType { - *self.handle.get(ctx.as_context_ref().objects()).ty() + pub fn ty(&self, ctx: &impl AsStoreRef) -> TableType { + *self.handle.get(ctx.as_store_ref().objects()).ty() } /// Retrieves an element of the table at the provided `index`. - pub fn get(&self, ctx: &mut impl AsContextMut, index: u32) -> Option { - let item = self.handle.get(ctx.as_context_ref().objects()).get(index)?; + pub fn get(&self, ctx: &mut impl AsStoreMut, index: u32) -> Option { + let item = self.handle.get(ctx.as_store_ref().objects()).get(index)?; Some(value_from_table_element(ctx, item)) } /// Sets an element `val` in the Table at the provided `index`. pub fn set( &self, - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, index: u32, val: Value, ) -> Result<(), RuntimeError> { let item = value_to_table_element(ctx, val)?; - set_table_item( - self.handle.get_mut(ctx.as_context_mut().objects_mut()), - index, - item, - ) + set_table_item(self.handle.get_mut(ctx.objects_mut()), index, item) } /// Retrieves the size of the `Table` (in elements) - pub fn size(&self, ctx: &impl AsContextRef) -> u32 { - self.handle.get(ctx.as_context_ref().objects()).size() + pub fn size(&self, ctx: &impl AsStoreRef) -> u32 { + self.handle.get(ctx.as_store_ref().objects()).size() } /// Grows the size of the `Table` by `delta`, initializating @@ -129,13 +125,13 @@ impl Table { /// Returns an error if the `delta` is out of bounds for the table. pub fn grow( &self, - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, delta: u32, init: Value, ) -> Result { let item = value_to_table_element(ctx, init)?; self.handle - .get_mut(ctx.as_context_mut().objects_mut()) + .get_mut(ctx.objects_mut()) .grow(delta, item) .ok_or_else(|| RuntimeError::new(format!("failed to grow table by `{}`", delta))) } @@ -148,19 +144,19 @@ impl Table { /// Returns an error if the range is out of bounds of either the source or /// destination tables. pub fn copy( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, dst_table: &Self, dst_index: u32, src_table: &Self, src_index: u32, len: u32, ) -> Result<(), RuntimeError> { - if dst_table.handle.context_id() != src_table.handle.context_id() { + if dst_table.handle.store_id() != src_table.handle.store_id() { return Err(RuntimeError::new( "cross-`Context` table copies are not supported", )); } - let mut ctx = ctx.as_context_mut(); + let ctx = ctx; if dst_table.handle.internal_handle() == src_table.handle.internal_handle() { let table = dst_table.handle.get_mut(ctx.objects_mut()); table.copy_within(dst_index, src_index, len) @@ -176,19 +172,19 @@ impl Table { } pub(crate) fn from_vm_extern( - ctx: &mut impl AsContextMut, - internal: InternalContextHandle, + ctx: &mut impl AsStoreMut, + internal: InternalStoreHandle, ) -> Self { Self { handle: unsafe { - ContextHandle::from_internal(ctx.as_context_ref().objects().id(), internal) + StoreHandle::from_internal(ctx.as_store_ref().objects().id(), internal) }, } } /// Checks whether this `Table` can be used with the given context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { - self.handle.context_id() == ctx.as_context_ref().objects().id() + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { + self.handle.store_id() == ctx.as_store_ref().objects().id() } pub(crate) fn to_vm_extern(&self) -> VMExtern { diff --git a/lib/api/src/sys/function_env.rs b/lib/api/src/sys/function_env.rs new file mode 100644 index 00000000000..c2fd67018c6 --- /dev/null +++ b/lib/api/src/sys/function_env.rs @@ -0,0 +1,120 @@ +use std::{any::Any, marker::PhantomData}; + +use wasmer_vm::{StoreHandle, StoreObjects, VMFunctionEnvironment}; + +use crate::{AsStoreMut, AsStoreRef, StoreMut, StoreRef}; + +#[derive(Debug)] +#[repr(transparent)] +/// An opaque reference to a function environment. +/// The function environment data is owned by the `Store`. +pub struct FunctionEnv { + pub(crate) handle: StoreHandle, + _phantom: PhantomData, +} + +impl FunctionEnv { + /// Make a new extern reference + pub fn new(store: &mut impl AsStoreMut, value: T) -> Self + where + T: Any + Send + 'static + Sized, + { + Self { + handle: StoreHandle::new( + store.as_store_mut().objects_mut(), + VMFunctionEnvironment::new(value), + ), + _phantom: PhantomData, + } + } + + /// Get the data as reference + pub fn as_ref<'a>(&self, store: &'a impl AsStoreMut) -> &'a T + where + T: Any + Send + 'static + Sized, + { + self.handle + .get(store.as_store_ref().objects()) + .as_ref() + .downcast_ref::() + .unwrap() + } + + /// Get the data as mutable + pub fn as_mut<'a>(&self, store: &'a mut impl AsStoreMut) -> &'a mut T + where + T: Any + Send + 'static + Sized, + { + self.handle + .get_mut(store.objects_mut()) + .as_mut() + .downcast_mut::() + .unwrap() + } + + /// Convert it into a `FunctionEnvMut` + pub fn into_mut(self, store: &mut impl AsStoreMut) -> FunctionEnvMut + where + T: Any + Send + 'static + Sized, + { + FunctionEnvMut { + store_mut: store.as_store_mut(), + func_env: self, + } + } +} + +impl Clone for FunctionEnv { + fn clone(&self) -> Self { + Self { + handle: self.handle.clone(), + _phantom: self._phantom, + } + } +} + +/// A temporary handle to a [`Context`]. +pub struct FunctionEnvMut<'a, T: 'a> { + pub(crate) store_mut: StoreMut<'a>, + pub(crate) func_env: FunctionEnv, +} + +impl FunctionEnvMut<'_, T> { + /// Returns a reference to the host state in this context. + pub fn data(&self) -> &T { + self.func_env.as_ref(&self.store_mut) + } + + /// Returns a mutable- reference to the host state in this context. + pub fn data_mut(&mut self) -> &mut T { + self.func_env.as_mut(&mut self.store_mut) + } + + /// Borrows a new mutable reference + pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> { + FunctionEnvMut { + store_mut: self.store_mut.as_store_mut(), + func_env: self.func_env.clone(), + } + } +} + +impl AsStoreRef for FunctionEnvMut<'_, T> { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { + inner: self.store_mut.inner, + } + } +} + +impl AsStoreMut for FunctionEnvMut<'_, T> { + fn as_store_mut(&mut self) -> StoreMut<'_> { + StoreMut { + inner: self.store_mut.inner, + } + } + #[inline] + fn objects_mut(&mut self) -> &mut StoreObjects { + &mut self.store_mut.inner.objects + } +} diff --git a/lib/api/src/sys/imports.rs b/lib/api/src/sys/imports.rs index 5c479c54b3c..a93171a3115 100644 --- a/lib/api/src/sys/imports.rs +++ b/lib/api/src/sys/imports.rs @@ -16,19 +16,19 @@ use wasmer_types::ImportError; /// /// # Usage: /// ```no_run -/// use wasmer::{ContextMut, Exports, Module, Instance, imports, Imports, Function}; -/// # fn foo_test(mut ctx: ContextMut<()>, module: Module) { +/// use wasmer::{Store, Exports, Module, Instance, imports, Imports, Function, FunctionEnv, FunctionEnvMut}; +/// # fn foo_test(mut env: FunctionEnv<()>, mut store: &mut Store, module: Module) { /// -/// let host_fn = Function::new_native(&mut ctx, foo); +/// let host_fn = Function::new_native(&mut store, &env, foo); /// let import_object: Imports = imports! { /// "env" => { /// "foo" => host_fn, /// }, /// }; /// -/// let instance = Instance::new(&mut ctx, &module, &import_object).expect("Could not instantiate module."); +/// let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); /// -/// fn foo(_ctx: ContextMut<()>, n: i32) -> i32 { +/// fn foo(_ctx: FunctionEnvMut<()>, n: i32) -> i32 { /// n /// } /// @@ -97,15 +97,15 @@ impl Imports { /// /// # Usage /// ```no_run - /// # use wasmer::Context as WasmerContext; - /// # let store = Default::default(); - /// # let mut ctx = WasmerContext::new(&store, ()); - /// use wasmer::{ContextMut, Imports, Function}; - /// fn foo(_ctx: ContextMut<()>, n: i32) -> i32 { + /// # use wasmer::{FunctionEnv, Store}; + /// # let mut store: Store = Default::default(); + /// # let env = FunctionEnv::new(&mut store, ()); + /// use wasmer::{StoreMut, Imports, Function, FunctionEnvMut}; + /// fn foo(_ctx: FunctionEnvMut<()>, n: i32) -> i32 { /// n /// } /// let mut import_object = Imports::new(); - /// import_object.define("env", "foo", Function::new_native(&mut ctx, foo)); + /// import_object.define("env", "foo", Function::new_native(&mut store, &env, foo)); /// ``` pub fn define(&mut self, ns: &str, name: &str, val: impl Into) { self.map @@ -210,19 +210,18 @@ impl fmt::Debug for Imports { /// # Usage /// /// ``` -/// # use wasmer::{ContextMut, Function, Store}; -/// # use wasmer::Context as WasmerContext; -/// # let store = Store::default(); -/// # let mut ctx = WasmerContext::new(&store, ()); +/// # use wasmer::{StoreMut, Function, Store, FunctionEnv, FunctionEnvMut}; +/// # let mut store = Store::default(); +/// # let env = FunctionEnv::new(&mut store, ()); /// use wasmer::imports; /// /// let import_object = imports! { /// "env" => { -/// "foo" => Function::new_native(&mut ctx, foo) +/// "foo" => Function::new_native(&mut store, &env, foo) /// }, /// }; /// -/// fn foo(_ctx: ContextMut<()>, n: i32) -> i32 { +/// fn foo(_env: FunctionEnvMut<()>, n: i32) -> i32 { /// n /// } /// ``` @@ -271,18 +270,15 @@ macro_rules! import_namespace { #[cfg(test)] mod test { - use crate::sys::exports::Exportable; - use crate::sys::Context as WasmerContext; - use crate::sys::Exports; - use crate::sys::{Global, Store, Value}; + use crate::sys::FunctionEnv; + use crate::sys::{AsStoreMut, Global, Store, Value}; use wasmer_types::Type; use wasmer_vm::VMExtern; - /* + #[test] fn namespace() { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let g1 = Global::new(&mut ctx, Value::I32(0)); + let mut store = Store::default(); + let g1 = Global::new(&mut store, Value::I32(0)); let namespace = namespace! { "happy" => g1 }; @@ -294,73 +290,72 @@ mod test { assert!( if let VMExtern::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { - happy_dog_global.get(&mut ctx).ty == Type::I32 + (*happy_dog_global.get(store.objects_mut()).ty()).ty == Type::I32 } else { false } ); } - */ + #[test] fn imports_macro_allows_trailing_comma_and_none() { - use crate::sys::ContextMut; use crate::sys::Function; + use crate::sys::FunctionEnvMut; - let store = Default::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store: Store = Default::default(); + let env = FunctionEnv::new(&mut store, ()); - fn func(_ctx: ContextMut<()>, arg: i32) -> i32 { + fn func(_ctx: FunctionEnvMut<()>, arg: i32) -> i32 { arg + 1 } let _ = imports! { "env" => { - "func" => Function::new_native(&mut ctx, func), + "func" => Function::new_native(&mut store, &env, func), }, }; let _ = imports! { "env" => { - "func" => Function::new_native(&mut ctx, func), + "func" => Function::new_native(&mut store, &env, func), } }; let _ = imports! { "env" => { - "func" => Function::new_native(&mut ctx, func), + "func" => Function::new_native(&mut store, &env, func), }, "abc" => { - "def" => Function::new_native(&mut ctx, func), + "def" => Function::new_native(&mut store, &env, func), } }; let _ = imports! { "env" => { - "func" => Function::new_native(&mut ctx, func) + "func" => Function::new_native(&mut store, &env, func) }, }; let _ = imports! { "env" => { - "func" => Function::new_native(&mut ctx, func) + "func" => Function::new_native(&mut store, &env, func) } }; let _ = imports! { "env" => { - "func1" => Function::new_native(&mut ctx, func), - "func2" => Function::new_native(&mut ctx, func) + "func1" => Function::new_native(&mut store, &env, func), + "func2" => Function::new_native(&mut store, &env, func) } }; let _ = imports! { "env" => { - "func1" => Function::new_native(&mut ctx, func), - "func2" => Function::new_native(&mut ctx, func), + "func1" => Function::new_native(&mut store, &env, func), + "func2" => Function::new_native(&mut store, &env, func), } }; } #[test] fn chaining_works() { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); - let g = Global::new(&mut ctx, Value::I32(0)); + let g = Global::new(&mut store, Value::I32(0)); let mut imports1 = imports! { "dog" => { @@ -390,10 +385,9 @@ mod test { #[test] fn extending_conflict_overwrites() { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let g1 = Global::new(&mut ctx, Value::I32(0)); - let g2 = Global::new(&mut ctx, Value::I64(0)); + let mut store = Store::default(); + let g1 = Global::new(&mut store, Value::I32(0)); + let g2 = Global::new(&mut store, Value::I64(0)); let mut imports1 = imports! { "dog" => { @@ -408,7 +402,7 @@ mod test { }; imports1.extend(&imports2); - let happy_dog_entry = imports1.get_export("dog", "happy").unwrap(); + let _happy_dog_entry = imports1.get_export("dog", "happy").unwrap(); /* assert!( if let Exports::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { @@ -419,10 +413,9 @@ mod test { ); */ // now test it in reverse - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let g1 = Global::new(&mut ctx, Value::I32(0)); - let g2 = Global::new(&mut ctx, Value::I64(0)); + let mut store = Store::default(); + let g1 = Global::new(&mut store, Value::I32(0)); + let g2 = Global::new(&mut store, Value::I64(0)); let imports1 = imports! { "dog" => { @@ -437,7 +430,7 @@ mod test { }; imports2.extend(&imports1); - let happy_dog_entry = imports2.get_export("dog", "happy").unwrap(); + let _happy_dog_entry = imports2.get_export("dog", "happy").unwrap(); /* assert!( if let Exports::Global(happy_dog_global) = happy_dog_entry.to_vm_extern() { diff --git a/lib/api/src/sys/instance.rs b/lib/api/src/sys/instance.rs index 547a12d1ba3..bcc4d6beb55 100644 --- a/lib/api/src/sys/instance.rs +++ b/lib/api/src/sys/instance.rs @@ -5,9 +5,9 @@ use crate::sys::module::Module; use crate::sys::{LinkError, RuntimeError}; use std::fmt; use thiserror::Error; -use wasmer_vm::{ContextHandle, InstanceHandle}; +use wasmer_vm::{InstanceHandle, StoreHandle}; -use super::context::AsContextMut; +use super::store::AsStoreMut; /// A WebAssembly Instance is a stateful, executable /// instance of a WebAssembly [`Module`]. @@ -19,7 +19,7 @@ use super::context::AsContextMut; /// Spec: #[derive(Clone)] pub struct Instance { - _handle: ContextHandle, + _handle: StoreHandle, module: Module, /// The exports for an instance. pub exports: Exports, @@ -59,13 +59,13 @@ pub enum InstantiationError { /// The module was compiled with a CPU feature that is not available on /// the current host. - #[error("missing requires CPU features: {0:?}")] + #[error("missing required CPU features: {0:?}")] CpuFeature(String), - /// Import from a different [`Context`]. - /// This error occurs when an import from a different context is used. - #[error("cannot mix imports from different contexts")] - BadContext, + /// Import from a different [`Store`]. + /// This error occurs when an import from a different store is used. + #[error("cannot mix imports from different stores")] + DifferentStores, } impl From for InstantiationError { @@ -87,17 +87,17 @@ impl Instance { /// /// ``` /// # use wasmer::{imports, Store, Module, Global, Value, Instance}; - /// # use wasmer::Context as WasmerContext; + /// # use wasmer::FunctionEnv; /// # fn main() -> anyhow::Result<()> { - /// let store = Store::default(); - /// let mut ctx = WasmerContext::new(&store, ()); + /// let mut store = Store::default(); + /// let env = FunctionEnv::new(&mut store, ()); /// let module = Module::new(&store, "(module)")?; /// let imports = imports!{ /// "host" => { - /// "var" => Global::new(&mut ctx, Value::I32(2)) + /// "var" => Global::new(&mut store, Value::I32(2)) /// } /// }; - /// let instance = Instance::new(&mut ctx, &module, &imports)?; + /// let instance = Instance::new(&mut store, &module, &imports)?; /// # Ok(()) /// # } /// ``` @@ -110,7 +110,7 @@ impl Instance { /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. pub fn new( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, module: &Module, imports: &Imports, ) -> Result { @@ -129,7 +129,7 @@ impl Instance { .collect::(); let instance = Self { - _handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), handle), + _handle: StoreHandle::new(ctx.objects_mut(), handle), module: module.clone(), exports, }; @@ -148,7 +148,7 @@ impl Instance { /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. pub fn new_by_index( - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, module: &Module, externs: &[Extern], ) -> Result { @@ -165,7 +165,7 @@ impl Instance { .collect::(); let instance = Self { - _handle: ContextHandle::new(ctx.as_context_mut().objects_mut(), handle), + _handle: StoreHandle::new(ctx.objects_mut(), handle), module: module.clone(), exports, }; diff --git a/lib/api/src/sys/mem_access.rs b/lib/api/src/sys/mem_access.rs index bc92dd140a1..debb46c0c68 100644 --- a/lib/api/src/sys/mem_access.rs +++ b/lib/api/src/sys/mem_access.rs @@ -12,8 +12,8 @@ use std::{ use thiserror::Error; use wasmer_types::ValueType; -use super::context::AsContextRef; use super::externals::memory::MemoryBuffer; +use super::store::AsStoreRef; /// Error for invalid [`Memory`] access. #[derive(Clone, Copy, Debug, Error)] @@ -62,7 +62,7 @@ pub struct WasmRef<'a, T: ValueType> { impl<'a, T: ValueType> WasmRef<'a, T> { /// Creates a new `WasmRef` at the given offset in a memory. #[inline] - pub fn new(ctx: &'a impl AsContextRef, memory: &'a Memory, offset: u64) -> Self { + pub fn new(ctx: &'a impl AsStoreRef, memory: &'a Memory, offset: u64) -> Self { Self { buffer: memory.buffer(ctx), offset, @@ -161,7 +161,7 @@ impl<'a, T: ValueType> WasmSlice<'a, T> { /// Returns a `MemoryAccessError` if the slice length overflows. #[inline] pub fn new( - ctx: &'a impl AsContextRef, + ctx: &'a impl AsStoreRef, memory: &'a Memory, offset: u64, len: u64, diff --git a/lib/api/src/sys/mod.rs b/lib/api/src/sys/mod.rs index e9e4ce3a40d..9eca8454d15 100644 --- a/lib/api/src/sys/mod.rs +++ b/lib/api/src/sys/mod.rs @@ -1,7 +1,7 @@ -mod context; mod exports; mod extern_ref; mod externals; +mod function_env; mod imports; mod instance; mod mem_access; @@ -13,18 +13,19 @@ mod store; mod tunables; mod value; -pub use crate::sys::context::{AsContextMut, AsContextRef, Context, ContextMut, ContextRef}; pub use crate::sys::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::sys::extern_ref::ExternRef; pub use crate::sys::externals::{ Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, Table, WasmTypeList, }; +pub use crate::sys::function_env::{FunctionEnv, FunctionEnvMut}; pub use crate::sys::imports::Imports; pub use crate::sys::instance::{Instance, InstantiationError}; pub use crate::sys::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter}; pub use crate::sys::module::Module; pub use crate::sys::native::TypedFunction; pub use crate::sys::native_type::NativeWasmTypeInto; +pub use crate::sys::store::{AsStoreMut, AsStoreRef, StoreMut, StoreRef}; pub use crate::sys::ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64}; pub use crate::sys::store::Store; @@ -81,7 +82,7 @@ If you wish to use more than one compiler, you can simply create the own store. use wasmer::{Store, Universal, Singlepass}; let engine = Universal::new(Singlepass::default()).engine(); -let store = Store::new_with_engine(&engine); +let mut store = Store::new_with_engine(&engine); ```"# ); diff --git a/lib/api/src/sys/module.rs b/lib/api/src/sys/module.rs index 3d23b4cbbda..ccd7c1d4299 100644 --- a/lib/api/src/sys/module.rs +++ b/lib/api/src/sys/module.rs @@ -1,5 +1,6 @@ -use crate::sys::store::Store; use crate::sys::InstantiationError; +use crate::AsStoreMut; +use crate::AsStoreRef; use std::fmt; use std::io; use std::path::Path; @@ -14,8 +15,6 @@ use wasmer_types::{ use wasmer_types::{ExportType, ImportType}; use wasmer_vm::InstanceHandle; -use super::context::AsContextMut; - #[derive(Error, Debug)] pub enum IoCompileError { /// An IO error @@ -51,7 +50,6 @@ pub struct Module { // In the future, this code should be refactored to properly describe the // ownership of the code and its metadata. artifact: Arc, - store: Store, } impl Module { @@ -81,7 +79,7 @@ impl Module { /// ``` /// use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = "(module)"; /// let module = Module::new(&store, wat)?; /// # Ok(()) @@ -93,7 +91,7 @@ impl Module { /// ``` /// use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// // The following is the same as: /// // (module /// // (type $t0 (func (param i32) (result i32))) @@ -115,7 +113,7 @@ impl Module { /// # } /// ``` #[allow(unreachable_code)] - pub fn new(store: &Store, bytes: impl AsRef<[u8]>) -> Result { + pub fn new(store: &impl AsStoreRef, bytes: impl AsRef<[u8]>) -> Result { #[cfg(feature = "wat")] let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| { CompileError::Wasm(WasmError::Generic(format!( @@ -128,7 +126,10 @@ impl Module { } /// Creates a new WebAssembly module from a file path. - pub fn from_file(store: &Store, file: impl AsRef) -> Result { + pub fn from_file( + store: &impl AsStoreRef, + file: impl AsRef, + ) -> Result { let file_ref = file.as_ref(); let canonical = file_ref.canonicalize()?; let wasm_bytes = std::fs::read(file_ref)?; @@ -145,7 +146,7 @@ impl Module { /// Opposed to [`Module::new`], this function is not compatible with /// the WebAssembly text format (if the "wat" feature is enabled for /// this crate). - pub fn from_binary(store: &Store, binary: &[u8]) -> Result { + pub fn from_binary(store: &impl AsStoreRef, binary: &[u8]) -> Result { Self::validate(store, binary)?; unsafe { Self::from_binary_unchecked(store, binary) } } @@ -158,7 +159,7 @@ impl Module { /// in environments where the WebAssembly modules are trusted and validated /// beforehand. pub unsafe fn from_binary_unchecked( - store: &Store, + store: &impl AsStoreRef, binary: &[u8], ) -> Result { let module = Self::compile(store, binary)?; @@ -171,13 +172,16 @@ impl Module { /// This validation is normally pretty fast and checks the enabled /// WebAssembly features in the Store Engine to assure deterministic /// validation of the Module. - pub fn validate(store: &Store, binary: &[u8]) -> Result<(), CompileError> { - store.engine().validate(binary) + pub fn validate(store: &impl AsStoreRef, binary: &[u8]) -> Result<(), CompileError> { + store.as_store_ref().engine().validate(binary) } - fn compile(store: &Store, binary: &[u8]) -> Result { - let artifact = store.engine().compile(binary, store.tunables())?; - Ok(Self::from_artifact(store, artifact)) + fn compile(store: &impl AsStoreRef, binary: &[u8]) -> Result { + let artifact = store + .as_store_ref() + .engine() + .compile(binary, store.as_store_ref().tunables())?; + Ok(Self::from_artifact(artifact)) } /// Serializes a module into a binary representation that the `Engine` @@ -188,7 +192,7 @@ impl Module { /// ```ignore /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # let module = Module::from_file(&store, "path/to/foo.wasm")?; /// let serialized = module.serialize()?; /// # Ok(()) @@ -206,7 +210,7 @@ impl Module { /// ```ignore /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # let module = Module::from_file(&store, "path/to/foo.wasm")?; /// module.serialize_to_file("path/to/foo.so")?; /// # Ok(()) @@ -234,14 +238,17 @@ impl Module { /// ```ignore /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let module = Module::deserialize(&store, serialized_data)?; /// # Ok(()) /// # } /// ``` - pub unsafe fn deserialize(store: &Store, bytes: &[u8]) -> Result { - let artifact = store.engine().deserialize(bytes)?; - Ok(Self::from_artifact(store, artifact)) + pub unsafe fn deserialize( + store: &impl AsStoreRef, + bytes: &[u8], + ) -> Result { + let artifact = store.as_store_ref().engine().deserialize(bytes)?; + Ok(Self::from_artifact(artifact)) } /// Deserializes a a serialized Module located in a `Path` into a `Module`. @@ -255,47 +262,48 @@ impl Module { /// /// ```ignore /// # use wasmer::*; - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// # fn main() -> anyhow::Result<()> { /// let module = Module::deserialize_from_file(&store, path)?; /// # Ok(()) /// # } /// ``` pub unsafe fn deserialize_from_file( - store: &Store, + store: &impl AsStoreRef, path: impl AsRef, ) -> Result { - let artifact = store.engine().deserialize_from_file(path.as_ref())?; - Ok(Self::from_artifact(store, artifact)) + let artifact = store + .as_store_ref() + .engine() + .deserialize_from_file(path.as_ref())?; + Ok(Self::from_artifact(artifact)) } - fn from_artifact(store: &Store, artifact: Arc) -> Self { - Self { - store: store.clone(), - artifact, - } + fn from_artifact(artifact: Arc) -> Self { + Self { artifact } } pub(crate) fn instantiate( &self, - ctx: &mut impl AsContextMut, + store: &mut impl AsStoreMut, imports: &[crate::Extern], ) -> Result { // Ensure all imports come from the same context. for import in imports { - if !import.is_from_context(ctx) { - return Err(InstantiationError::BadContext); + if !import.is_from_store(store) { + return Err(InstantiationError::DifferentStores); } } - + let mut store_mut = store.as_store_mut(); + let (tunables, objects) = store_mut.tunables_and_objects_mut(); unsafe { let mut instance_handle = self.artifact.instantiate( - self.store.tunables(), + tunables, &imports .iter() .map(crate::Extern::to_vm_extern) .collect::>(), - ctx.as_context_mut().objects_mut(), + objects, )?; // After the instance handle is created, we need to initialize @@ -303,8 +311,10 @@ impl Module { // of this steps traps, we still need to keep the instance alive // as some of the Instance elements may have placed in other // instance tables. - self.artifact - .finish_instantiation(&self.store, &mut instance_handle)?; + self.artifact.finish_instantiation( + store.as_store_ref().signal_handler(), + &mut instance_handle, + )?; Ok(instance_handle) } @@ -320,7 +330,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = "(module $moduleName)"; /// let module = Module::new(&store, wat)?; /// assert_eq!(module.name(), Some("moduleName")); @@ -343,7 +353,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = "(module)"; /// let mut module = Module::new(&store, wat)?; /// assert_eq!(module.name(), None); @@ -371,7 +381,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = r#"(module /// (import "host" "func1" (func)) /// (import "host" "func2" (func)) @@ -399,7 +409,7 @@ impl Module { /// ``` /// # use wasmer::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let mut store = Store::default(); /// let wat = r#"(module /// (func (export "namedfunc")) /// (memory (export "namedmemory") 1) @@ -427,11 +437,6 @@ impl Module { self.artifact.module_ref().custom_sections(name) } - /// Returns the [`Store`] where the `Instance` belongs. - pub fn store(&self) -> &Store { - &self.store - } - /// The ABI of the ModuleInfo is very unstable, we refactor it very often. /// This function is public because in some cases it can be useful to get some /// extra information from the module. diff --git a/lib/api/src/sys/native.rs b/lib/api/src/sys/native.rs index 3866509be8e..b9aab2647db 100644 --- a/lib/api/src/sys/native.rs +++ b/lib/api/src/sys/native.rs @@ -10,7 +10,7 @@ use std::marker::PhantomData; use crate::sys::{ - AsContextMut, FromToNativeWasmType, Function, NativeWasmTypeInto, RuntimeError, WasmTypeList, + AsStoreMut, FromToNativeWasmType, Function, NativeWasmTypeInto, RuntimeError, WasmTypeList, }; use wasmer_types::RawValue; @@ -66,17 +66,17 @@ macro_rules! impl_native_traits { /// Call the typed func and return results. #[allow(unused_mut)] #[allow(clippy::too_many_arguments)] - pub fn call(&self, ctx: &mut impl AsContextMut, $( $x: $x, )* ) -> Result { + pub fn call(&self, ctx: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result { let anyfunc = unsafe { *self.func .handle - .get(ctx.as_context_ref().objects()) + .get(ctx.as_store_ref().objects()) .anyfunc .as_ptr() .as_ref() }; // Ensure all parameters come from the same context. - if $(!FromToNativeWasmType::is_from_context(&$x, ctx) ||)* false { + if $(!FromToNativeWasmType::is_from_store(&$x, ctx) ||)* false { return Err(RuntimeError::new( "cross-`Context` values are not supported", )); @@ -99,7 +99,7 @@ macro_rules! impl_native_traits { }; unsafe { wasmer_vm::wasmer_call_trampoline( - ctx.as_context_ref().store(), + ctx.as_store_ref().signal_handler(), anyfunc.vmctx, anyfunc.call_trampoline, anyfunc.func_ptr, diff --git a/lib/api/src/sys/native_type.rs b/lib/api/src/sys/native_type.rs index 746c3b21585..2b9b54df19e 100644 --- a/lib/api/src/sys/native_type.rs +++ b/lib/api/src/sys/native_type.rs @@ -6,133 +6,133 @@ use wasmer_vm::{VMExternRef, VMFuncRef}; use crate::{ExternRef, Function}; -use super::context::AsContextMut; +use super::store::AsStoreMut; /// `NativeWasmTypeInto` performs conversions from and into `NativeWasmType` /// types with a context. pub trait NativeWasmTypeInto: NativeWasmType + Sized { #[doc(hidden)] - fn into_abi(self, ctx: &mut impl AsContextMut) -> Self::Abi; + fn into_abi(self, ctx: &mut impl AsStoreMut) -> Self::Abi; #[doc(hidden)] - unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self; + unsafe fn from_abi(ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self; /// Convert self to raw value representation. - fn into_raw(self, ctx: &mut impl AsContextMut) -> RawValue; + fn into_raw(self, ctx: &mut impl AsStoreMut) -> RawValue; /// Convert to self from raw value representation. /// /// # Safety /// - unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: RawValue) -> Self; + unsafe fn from_raw(ctx: &mut impl AsStoreMut, raw: RawValue) -> Self; } impl NativeWasmTypeInto for i32 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> RawValue { RawValue { i32: self } } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: RawValue) -> Self { raw.i32 } } impl NativeWasmTypeInto for i64 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> RawValue { RawValue { i64: self } } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: RawValue) -> Self { raw.i64 } } impl NativeWasmTypeInto for f32 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> RawValue { RawValue { f32: self } } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: RawValue) -> Self { raw.f32 } } impl NativeWasmTypeInto for f64 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> RawValue { RawValue { f64: self } } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: RawValue) -> Self { raw.f64 } } impl NativeWasmTypeInto for u128 { #[inline] - unsafe fn from_abi(_ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(_ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { abi } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> RawValue { RawValue { u128: self } } #[inline] - unsafe fn from_raw(_ctx: &mut impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(_ctx: &mut impl AsStoreMut, raw: RawValue) -> Self { raw.u128 } } @@ -144,23 +144,23 @@ impl NativeWasmType for ExternRef { impl NativeWasmTypeInto for Option { #[inline] - unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { VMExternRef::from_raw(RawValue { externref: abi }) .map(|e| ExternRef::from_vm_externref(ctx, e)) } #[inline] - fn into_abi(self, _ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, _ctx: &mut impl AsStoreMut) -> Self::Abi { self.map_or(0, |e| unsafe { e.vm_externref().into_raw().externref }) } #[inline] - fn into_raw(self, _ctx: &mut impl AsContextMut) -> RawValue { + fn into_raw(self, _ctx: &mut impl AsStoreMut) -> RawValue { self.map_or(RawValue { externref: 0 }, |e| e.vm_externref().into_raw()) } #[inline] - unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(ctx: &mut impl AsStoreMut, raw: RawValue) -> Self { VMExternRef::from_raw(raw).map(|e| ExternRef::from_vm_externref(ctx, e)) } } @@ -172,22 +172,22 @@ impl NativeWasmType for Function { impl NativeWasmTypeInto for Option { #[inline] - unsafe fn from_abi(ctx: &mut impl AsContextMut, abi: Self::Abi) -> Self { + unsafe fn from_abi(ctx: &mut impl AsStoreMut, abi: Self::Abi) -> Self { VMFuncRef::from_raw(RawValue { funcref: abi }).map(|f| Function::from_vm_funcref(ctx, f)) } #[inline] - fn into_abi(self, ctx: &mut impl AsContextMut) -> Self::Abi { + fn into_abi(self, ctx: &mut impl AsStoreMut) -> Self::Abi { self.map_or(0, |f| unsafe { f.vm_funcref(ctx).into_raw().externref }) } #[inline] - fn into_raw(self, ctx: &mut impl AsContextMut) -> RawValue { + fn into_raw(self, ctx: &mut impl AsStoreMut) -> RawValue { self.map_or(RawValue { externref: 0 }, |e| e.vm_funcref(ctx).into_raw()) } #[inline] - unsafe fn from_raw(ctx: &mut impl AsContextMut, raw: RawValue) -> Self { + unsafe fn from_raw(ctx: &mut impl AsStoreMut, raw: RawValue) -> Self { VMFuncRef::from_raw(raw).map(|f| Function::from_vm_funcref(ctx, f)) } } diff --git a/lib/api/src/sys/ptr.rs b/lib/api/src/sys/ptr.rs index 1f46dc84b9b..8a430e6e4dd 100644 --- a/lib/api/src/sys/ptr.rs +++ b/lib/api/src/sys/ptr.rs @@ -5,13 +5,11 @@ use std::convert::TryFrom; use std::{fmt, marker::PhantomData, mem}; use wasmer_types::ValueType; -use super::context::AsContextRef; - -pub use wasmer_types::MemorySize; +use super::store::AsStoreRef; pub use wasmer_types::Memory32; - pub use wasmer_types::Memory64; +pub use wasmer_types::MemorySize; /// Alias for `WasmPtr. pub type WasmPtr64 = WasmPtr; @@ -23,8 +21,8 @@ pub type WasmPtr64 = WasmPtr; /// ``` /// # use wasmer::Memory; /// # use wasmer::WasmPtr; -/// # use wasmer::ContextMut; -/// pub fn host_import(mut ctx: ContextMut<()>, memory: Memory, ptr: WasmPtr) { +/// # use wasmer::FunctionEnvMut; +/// pub fn host_import(mut ctx: FunctionEnvMut<()>, memory: Memory, ptr: WasmPtr) { /// let derefed_ptr = ptr.deref(&mut ctx, &memory); /// let inner_val: u32 = derefed_ptr.read().expect("pointer in bounds"); /// println!("Got {} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); @@ -39,7 +37,7 @@ pub type WasmPtr64 = WasmPtr; /// # use wasmer::Memory; /// # use wasmer::WasmPtr; /// # use wasmer::ValueType; -/// # use wasmer::ContextMut; +/// # use wasmer::FunctionEnvMut; /// /// // This is safe as the 12 bytes represented by this struct /// // are valid for all bit combinations. @@ -51,7 +49,7 @@ pub type WasmPtr64 = WasmPtr; /// z: f32 /// } /// -/// fn update_vector_3(mut ctx: ContextMut<()>, memory: Memory, ptr: WasmPtr) { +/// fn update_vector_3(mut ctx: FunctionEnvMut<()>, memory: Memory, ptr: WasmPtr) { /// let derefed_ptr = ptr.deref(&mut ctx, &memory); /// let mut inner_val: V3 = derefed_ptr.read().expect("pointer in bounds"); /// println!("Got {:?} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); @@ -144,13 +142,13 @@ impl WasmPtr { /// Creates a `WasmRef` from this `WasmPtr` which allows reading and /// mutating of the value being pointed to. #[inline] - pub fn deref<'a>(self, ctx: &'a impl AsContextRef, memory: &'a Memory) -> WasmRef<'a, T> { + pub fn deref<'a>(self, ctx: &'a impl AsStoreRef, memory: &'a Memory) -> WasmRef<'a, T> { WasmRef::new(ctx, memory, self.offset.into()) } /// Reads the address pointed to by this `WasmPtr` in a memory. #[inline] - pub fn read(self, ctx: &impl AsContextRef, memory: &Memory) -> Result { + pub fn read(self, ctx: &impl AsStoreRef, memory: &Memory) -> Result { self.deref(&ctx, memory).read() } @@ -158,7 +156,7 @@ impl WasmPtr { #[inline] pub fn write( self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, memory: &Memory, val: T, ) -> Result<(), MemoryAccessError> { @@ -173,7 +171,7 @@ impl WasmPtr { #[inline] pub fn slice<'a>( self, - ctx: &'a impl AsContextRef, + ctx: &'a impl AsStoreRef, memory: &'a Memory, len: M::Offset, ) -> Result, MemoryAccessError> { @@ -187,7 +185,7 @@ impl WasmPtr { #[inline] pub fn read_until( self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, memory: &Memory, mut end: impl FnMut(&T) -> bool, ) -> Result, MemoryAccessError> { @@ -212,7 +210,7 @@ impl WasmPtr { #[inline] pub fn read_utf8_string( self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, memory: &Memory, len: M::Offset, ) -> Result { @@ -227,7 +225,7 @@ impl WasmPtr { #[inline] pub fn read_utf8_string_with_nul( self, - ctx: &impl AsContextRef, + ctx: &impl AsStoreRef, memory: &Memory, ) -> Result { let vec = self.read_until(ctx, memory, |&byte| byte == 0)?; diff --git a/lib/api/src/sys/store.rs b/lib/api/src/sys/store.rs index ad8c2bce2c7..862ebda5b61 100644 --- a/lib/api/src/sys/store.rs +++ b/lib/api/src/sys/store.rs @@ -1,9 +1,21 @@ use crate::sys::tunables::BaseTunables; use std::fmt; -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use wasmer_compiler::CompilerConfig; use wasmer_compiler::{Engine, Tunables, Universal}; -use wasmer_vm::{init_traps, TrapHandler, TrapHandlerFn}; +use wasmer_vm::{init_traps, TrapHandlerFn}; + +use wasmer_vm::StoreObjects; + +/// We require the context to have a fixed memory address for its lifetime since +/// various bits of the VM have raw pointers that point back to it. Hence we +/// wrap the actual context in a box. +pub(crate) struct StoreInner { + pub(crate) objects: StoreObjects, + pub(crate) engine: Arc, + pub(crate) tunables: Box, + pub(crate) trap_handler: Option>>, +} /// The store represents all global state that can be manipulated by /// WebAssembly programs. It consists of the runtime representation @@ -15,11 +27,8 @@ use wasmer_vm::{init_traps, TrapHandler, TrapHandlerFn}; /// [`Tunables`] (that are used to create the memories, tables and globals). /// /// Spec: -#[derive(Clone)] pub struct Store { - engine: Arc, - tunables: Arc, - trap_handler: Arc>>>, + pub(crate) inner: Box, } impl Store { @@ -38,9 +47,8 @@ impl Store { } /// Set the trap handler in this store. - pub fn set_trap_handler(&self, handler: Option>) { - let mut m = self.trap_handler.write().unwrap(); - *m = handler; + pub fn set_trap_handler(&mut self, handler: Option>>) { + self.inner.trap_handler = handler; } /// Creates a new `Store` with a specific [`Engine`] and [`Tunables`]. @@ -53,45 +61,21 @@ impl Store { init_traps(); Self { - engine: engine.cloned(), - tunables: Arc::new(tunables), - trap_handler: Arc::new(RwLock::new(None)), + inner: Box::new(StoreInner { + objects: Default::default(), + engine: engine.cloned(), + tunables: Box::new(tunables), + trap_handler: None, + }), } } - - /// Returns the [`Tunables`]. - pub fn tunables(&self) -> &dyn Tunables { - self.tunables.as_ref() - } - - /// Returns the [`Engine`]. - pub fn engine(&self) -> &Arc { - &self.engine - } - - /// Checks whether two stores are identical. A store is considered - /// equal to another store if both have the same engine. The - /// tunables are excluded from the logic. - pub fn same(a: &Self, b: &Self) -> bool { - a.engine.id() == b.engine.id() - } -} - -impl PartialEq for Store { - fn eq(&self, other: &Self) -> bool { - Self::same(self, other) - } } -unsafe impl TrapHandler for Store { - fn custom_trap_handler(&self, call: &dyn Fn(&TrapHandlerFn) -> bool) -> bool { - if let Some(handler) = self.trap_handler.read().unwrap().as_ref() { - call(handler) - } else { - false - } - } -} +// impl PartialEq for Store { +// fn eq(&self, other: &Self) -> bool { +// Self::same(self, other) +// } +// } // This is required to be able to set the trap_handler in the // Store. @@ -139,8 +123,151 @@ impl Default for Store { } } +impl AsStoreRef for Store { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { inner: &self.inner } + } +} +impl AsStoreMut for Store { + fn as_store_mut(&mut self) -> StoreMut<'_> { + StoreMut { + inner: &mut self.inner, + } + } + fn objects_mut(&mut self) -> &mut StoreObjects { + &mut self.inner.objects + } +} + impl fmt::Debug for Store { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Store").finish() } } + +/// A temporary handle to a [`Context`]. +pub struct StoreRef<'a> { + pub(crate) inner: &'a StoreInner, +} + +impl<'a> StoreRef<'a> { + pub(crate) fn objects(&self) -> &'a StoreObjects { + &self.inner.objects + } + + /// Returns the [`Tunables`]. + pub fn tunables(&self) -> &dyn Tunables { + self.inner.tunables.as_ref() + } + + /// Returns the [`Engine`]. + pub fn engine(&self) -> &Arc { + &self.inner.engine + } + + /// Checks whether two stores are identical. A store is considered + /// equal to another store if both have the same engine. The + /// tunables are excluded from the logic. + pub fn same(a: &Self, b: &Self) -> bool { + a.inner.engine.id() == b.inner.engine.id() + } + + /// The signal handler + #[inline] + pub fn signal_handler(&self) -> Option<*const TrapHandlerFn<'static>> { + self.inner + .trap_handler + .as_ref() + .map(|handler| &*handler as *const _) + } +} + +/// A temporary handle to a [`Context`]. +pub struct StoreMut<'a> { + pub(crate) inner: &'a mut StoreInner, +} + +impl<'a> StoreMut<'a> { + /// Returns the [`Tunables`]. + pub fn tunables(&self) -> &dyn Tunables { + self.inner.tunables.as_ref() + } + + /// Returns the [`Engine`]. + pub fn engine(&self) -> &Arc { + &self.inner.engine + } + + /// Checks whether two stores are identical. A store is considered + /// equal to another store if both have the same engine. The + /// tunables are excluded from the logic. + pub fn same(a: &Self, b: &Self) -> bool { + a.inner.engine.id() == b.inner.engine.id() + } + + pub(crate) fn tunables_and_objects_mut(&mut self) -> (&dyn Tunables, &mut StoreObjects) { + (self.inner.tunables.as_ref(), &mut self.inner.objects) + } + + pub(crate) fn as_raw(&self) -> *mut StoreInner { + self.inner as *const StoreInner as *mut StoreInner + } + + pub(crate) unsafe fn from_raw(raw: *mut StoreInner) -> Self { + Self { inner: &mut *raw } + } +} + +/// Helper trait for a value that is convertible to a [`StoreRef`]. +pub trait AsStoreRef { + /// Returns a `StoreRef` pointing to the underlying context. + fn as_store_ref(&self) -> StoreRef<'_>; +} + +/// Helper trait for a value that is convertible to a [`StoreMut`]. +pub trait AsStoreMut: AsStoreRef { + /// Returns a `StoreMut` pointing to the underlying context. + fn as_store_mut(&mut self) -> StoreMut<'_>; + + /// Returns the ObjectMutable + fn objects_mut(&mut self) -> &mut StoreObjects; +} + +impl AsStoreRef for StoreRef<'_> { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { inner: self.inner } + } +} + +impl AsStoreRef for StoreMut<'_> { + fn as_store_ref(&self) -> StoreRef<'_> { + StoreRef { inner: self.inner } + } +} +impl AsStoreMut for StoreMut<'_> { + fn as_store_mut(&mut self) -> StoreMut<'_> { + StoreMut { inner: self.inner } + } + fn objects_mut(&mut self) -> &mut StoreObjects { + &mut self.inner.objects + } +} + +impl AsStoreRef for &'_ T { + fn as_store_ref(&self) -> StoreRef<'_> { + T::as_store_ref(*self) + } +} +impl AsStoreRef for &'_ mut T { + fn as_store_ref(&self) -> StoreRef<'_> { + T::as_store_ref(*self) + } +} +impl AsStoreMut for &'_ mut T { + fn as_store_mut(&mut self) -> StoreMut<'_> { + T::as_store_mut(*self) + } + fn objects_mut(&mut self) -> &mut StoreObjects { + T::objects_mut(*self) + } +} diff --git a/lib/api/src/sys/value.rs b/lib/api/src/sys/value.rs index 03414a70483..d681692fcb3 100644 --- a/lib/api/src/sys/value.rs +++ b/lib/api/src/sys/value.rs @@ -9,8 +9,7 @@ use wasmer_vm::VMFuncRef; use crate::ExternRef; use crate::Function; -use super::context::AsContextMut; -use super::context::AsContextRef; +use super::store::{AsStoreMut, AsStoreRef}; pub use wasmer_types::RawValue; @@ -92,7 +91,7 @@ impl Value { } /// Converts the `Value` into a `RawValue`. - pub fn as_raw(&self, ctx: &impl AsContextRef) -> RawValue { + pub fn as_raw(&self, ctx: &impl AsStoreRef) -> RawValue { match *self { Self::I32(i32) => RawValue { i32 }, Self::I64(i64) => RawValue { i64 }, @@ -111,7 +110,7 @@ impl Value { /// /// # Safety /// - pub unsafe fn from_raw(ctx: &mut impl AsContextMut, ty: Type, raw: RawValue) -> Self { + pub unsafe fn from_raw(ctx: &mut impl AsStoreMut, ty: Type, raw: RawValue) -> Self { match ty { Type::I32 => Self::I32(raw.i32), Type::I64 => Self::I64(raw.i64), @@ -134,7 +133,7 @@ impl Value { /// /// Externref and funcref values are tied to a context and can only be used /// with that context. - pub fn is_from_context(&self, ctx: &impl AsContextRef) -> bool { + pub fn is_from_store(&self, ctx: &impl AsStoreRef) -> bool { match self { Self::I32(_) | Self::I64(_) @@ -143,8 +142,8 @@ impl Value { | Self::V128(_) | Self::ExternRef(None) | Self::FuncRef(None) => true, - Self::ExternRef(Some(e)) => e.is_from_context(ctx), - Self::FuncRef(Some(f)) => f.is_from_context(ctx), + Self::ExternRef(Some(e)) => e.is_from_store(ctx), + Self::FuncRef(Some(f)) => f.is_from_store(ctx), } } diff --git a/lib/api/tests/js_externals.rs b/lib/api/tests/js_externals.rs index 187e6a6b1fe..a17aae4b76d 100644 --- a/lib/api/tests/js_externals.rs +++ b/lib/api/tests/js_externals.rs @@ -5,20 +5,20 @@ mod js { #[wasm_bindgen_test] fn global_new() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); - let global = Global::new(&mut ctx, Value::I32(10)); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); + let global = Global::new(&mut store, Value::I32(10)); assert_eq!( - global.ty(&ctx), + global.ty(&store), GlobalType { ty: Type::I32, mutability: Mutability::Const } ); - let global_mut = Global::new_mut(&mut ctx, Value::I32(10)); + let global_mut = Global::new_mut(&mut store, Value::I32(10)); assert_eq!( - global_mut.ty(&ctx), + global_mut.ty(&store), GlobalType { ty: Type::I32, mutability: Mutability::Var @@ -28,50 +28,50 @@ mod js { #[wasm_bindgen_test] fn global_get() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); - let global_i32 = Global::new(&mut ctx, Value::I32(10)); - assert_eq!(global_i32.get(&ctx), Value::I32(10)); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); + let global_i32 = Global::new(&mut store, Value::I32(10)); + assert_eq!(global_i32.get(&store), Value::I32(10)); // 64-bit values are not yet fully supported in some versions of Node // Commenting this tests for now: // let global_i64 = Global::new(&store, Value::I64(20)); // assert_eq!(global_i64.get(), Value::I64(20)); - let global_f32 = Global::new(&mut ctx, Value::F32(10.0)); - assert_eq!(global_f32.get(&ctx), Value::F32(10.0)); + let global_f32 = Global::new(&mut store, Value::F32(10.0)); + assert_eq!(global_f32.get(&store), Value::F32(10.0)); // let global_f64 = Global::new(&store, Value::F64(20.0)); // assert_eq!(global_f64.get(), Value::F64(20.0)); } #[wasm_bindgen_test] fn global_set() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); - let global_i32 = Global::new(&mut ctx, Value::I32(10)); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); + let global_i32 = Global::new(&mut store, Value::I32(10)); // Set on a constant should error - assert!(global_i32.set(&mut ctx, Value::I32(20)).is_err()); + assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); - let global_i32_mut = Global::new_mut(&mut ctx, Value::I32(10)); + let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); // Set on different type should error - assert!(global_i32_mut.set(&mut ctx, Value::I64(20)).is_err()); + assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); // Set on same type should succeed - global_i32_mut.set(&mut ctx, Value::I32(20)).unwrap(); - assert_eq!(global_i32_mut.get(&ctx), Value::I32(20)); + global_i32_mut.set(&mut store, Value::I32(20)).unwrap(); + assert_eq!(global_i32_mut.get(&store), Value::I32(20)); } #[wasm_bindgen_test] fn table_new() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: None, }; - let f = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>| {}); - let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f))).unwrap(); - assert_eq!(table.ty(&ctx), table_type); + let f = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>| {}); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))).unwrap(); + assert_eq!(table.ty(&store), table_type); // table.get() // Anyrefs not yet supported @@ -81,7 +81,7 @@ mod js { // maximum: None, // }; // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; - // assert_eq!(*table.ty(&ctx), table_type); + // assert_eq!(*table.ty(&store), table_type); } // Tables are not yet fully supported in Wasm @@ -90,16 +90,16 @@ mod js { // #[test] // #[ignore] // fn table_get() -> Result<()> { - // let store = Store::default(); - // let mut ctx = Context::new(&store, ()); + // let mut store = Store::default(); + // let mut env = FunctionEnv::new(&mut store, ()); // let table_type = TableType { // ty: Type::FuncRef, // minimum: 0, // maximum: Some(1), // }; - // let f = Function::new(&mut ctx, |num: i32| num + 1); + // let f = Function::new(&mut store, &env, |num: i32| num + 1); // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; - // assert_eq!(*table.ty(&ctx), table_type); + // assert_eq!(*table.ty(&store), table_type); // let _elem = table.get(0).unwrap(); // // assert_eq!(elem.funcref().unwrap(), f); // Ok(()) @@ -114,14 +114,14 @@ mod js { // #[test] // fn table_grow() -> Result<()> { - // let store = Store::default(); - // let mut ctx = Context::new(&store, ()); + // let mut store = Store::default(); + // let mut env = FunctionEnv::new(&mut store, ()); // let table_type = TableType { // ty: Type::FuncRef, // minimum: 0, // maximum: Some(10), // }; - // let f = Function::new(&mut ctx, |num: i32| num + 1); + // let f = Function::new(&mut store, &env, |num: i32| num + 1); // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; // // Growing to a bigger maximum should return None // let old_len = table.grow(12, Value::FuncRef(Some(f.clone()))); @@ -143,32 +143,32 @@ mod js { #[wasm_bindgen_test] fn memory_new() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); let memory_type = MemoryType { shared: false, minimum: Pages(0), maximum: Some(Pages(10)), }; - let memory = Memory::new(&mut ctx, memory_type).unwrap(); - assert_eq!(memory.size(&ctx), Pages(0)); - assert_eq!(memory.ty(&ctx), memory_type); + let memory = Memory::new(&mut store, memory_type).unwrap(); + assert_eq!(memory.size(&store), Pages(0)); + assert_eq!(memory.ty(&store), memory_type); } #[wasm_bindgen_test] fn memory_grow() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&mut ctx, desc).unwrap(); - assert_eq!(memory.size(&ctx), Pages(10)); + let memory = Memory::new(&mut store, desc).unwrap(); + assert_eq!(memory.size(&store), Pages(10)); - let result = memory.grow(&mut ctx, Pages(2)).unwrap(); + let result = memory.grow(&mut store, Pages(2)).unwrap(); assert_eq!(result, Pages(10)); - assert_eq!(memory.size(&ctx), Pages(12)); + assert_eq!(memory.size(&store), Pages(12)); - let result = memory.grow(&mut ctx, Pages(10)); + let result = memory.grow(&mut store, Pages(10)); assert!(result.is_err()); assert_eq!( result, @@ -181,235 +181,270 @@ mod js { #[wasm_bindgen_test] fn function_new() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<'_, ()>| {}); - assert_eq!(function.ty(&ctx).clone(), FunctionType::new(vec![], vec![])); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<'_, ()>, _a: i32| {}); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); + let function = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<'_, ()>| {}); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = + Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<'_, ()>, _a: i32| {}); + assert_eq!( + function.ty(&store).clone(), FunctionType::new(vec![Type::I32], vec![]) ); let function = Function::new_native( - &mut ctx, - |_ctx: ContextMut<'_, ()>, _a: i32, _b: i64, _c: f32, _d: f64| {}, + &mut store, + &env, + |_ctx: FunctionEnvMut<'_, ()>, _a: i32, _b: i64, _c: f32, _d: f64| {}, ); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<'_, ()>| -> i32 { 1 }); + let function = + Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<'_, ()>| -> i32 { + 1 + }); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), FunctionType::new(vec![], vec![Type::I32]) ); let function = Function::new_native( - &mut ctx, - |_ctx: ContextMut<'_, ()>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + &mut store, + &env, + |_ctx: FunctionEnvMut<'_, ()>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, ); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); } #[wasm_bindgen_test] fn function_new_env() { - let store = Store::default(); + let mut store = Store::default(); #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; - let mut ctx = Context::new(&store, my_env); + let mut env = FunctionEnv::new(&mut store, my_env); - let function = Function::new_native(&mut ctx, |_: ContextMut<'_, MyEnv>| {}); - assert_eq!(function.ty(&ctx).clone(), FunctionType::new(vec![], vec![])); - let function = Function::new_native(&mut ctx, |_: ContextMut<'_, MyEnv>, _a: i32| {}); + let function = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| {}); + assert_eq!( + function.ty(&store).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = + Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>, _a: i32| {}); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), FunctionType::new(vec![Type::I32], vec![]) ); let function = Function::new_native( - &mut ctx, - |_: ContextMut<'_, MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {}, + &mut store, + &env, + |_: FunctionEnvMut<'_, MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {}, ); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = Function::new_native(&mut ctx, |_: ContextMut<'_, MyEnv>| -> i32 { 1 }); + let function = + Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| -> i32 { + 1 + }); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), FunctionType::new(vec![], vec![Type::I32]) ); let function = Function::new_native( - &mut ctx, - |_: ContextMut<'_, MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + &mut store, + &env, + |_: FunctionEnvMut<'_, MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, ); assert_eq!( - function.ty(&ctx).clone(), + function.ty(&store).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); } #[wasm_bindgen_test] fn function_new_dynamic() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, ()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, ()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, ()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, ()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, ()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, function_type, - |_ctx: ContextMut<'_, ()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, ()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).params(), [Type::V128]); + assert_eq!(function.ty(&store).params(), [Type::V128]); assert_eq!( - function.ty(&ctx).results(), + function.ty(&store).results(), [Type::I32, Type::F32, Type::F64] ); } #[wasm_bindgen_test] fn function_new_dynamic_env() { - let store = Store::default(); + let mut store = Store::default(); #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; - let mut ctx = Context::new(&store, my_env); + let mut env = FunctionEnv::new(&mut store, my_env); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).clone(), function_type); + assert_eq!(function.ty(&store).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, function_type, - |_ctx: ContextMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&ctx).params(), [Type::V128]); + assert_eq!(function.ty(&store).params(), [Type::V128]); assert_eq!( - function.ty(&ctx).results(), + function.ty(&store).results(), [Type::I32, Type::F32, Type::F64] ); } #[wasm_bindgen_test] fn native_function_works() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); - let function = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>| {}); - let typed_function: TypedFunction<(), ()> = function.native(&mut ctx).unwrap(); - let result = typed_function.call(&mut ctx); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); + let function = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>| {}); + let typed_function: TypedFunction<(), ()> = function.native(&mut store).unwrap(); + let result = typed_function.call(&mut store); assert!(result.is_ok()); - let function = - Function::new_native(&mut ctx, |_: ContextMut<'_, ()>, a: i32| -> i32 { a + 1 }); - let typed_function: TypedFunction = function.native(&mut ctx).unwrap(); - assert_eq!(typed_function.call(&mut ctx, 3).unwrap(), 4); + let function = Function::new_native( + &mut store, + &env, + |_: FunctionEnvMut<'_, ()>, a: i32| -> i32 { a + 1 }, + ); + let typed_function: TypedFunction = function.native(&mut store).unwrap(); + assert_eq!(typed_function.call(&mut store, 3).unwrap(), 4); // fn rust_abi(a: i32, b: i64, c: f32, d: f64) -> u64 { // (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) // } - // let function = Function::new(&mut ctx, rust_abi); - // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = function.native(&mut ctx).unwrap(); + // let function = Function::new(&mut store, &env, rust_abi); + // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = function.native(&mut store).unwrap(); // assert_eq!(typed_function.call(8, 4, 1.5, 5.).unwrap(), 8415); - let function = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>| -> i32 { 1 }); - let typed_function: TypedFunction<(), i32> = function.native(&mut ctx).unwrap(); - assert_eq!(typed_function.call(&mut ctx).unwrap(), 1); + let function = + Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>| -> i32 { 1 }); + let typed_function: TypedFunction<(), i32> = function.native(&mut store).unwrap(); + assert_eq!(typed_function.call(&mut store).unwrap(), 1); - let function = Function::new_native(&mut ctx, |_: ContextMut<'_, ()>, _a: i32| {}); - let typed_function: TypedFunction = function.native(&mut ctx).unwrap(); - assert!(typed_function.call(&mut ctx, 4).is_ok()); + let function = + Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>, _a: i32| {}); + let typed_function: TypedFunction = function.native(&mut store).unwrap(); + assert!(typed_function.call(&mut store, 4).is_ok()); - // let function = Function::new(&mut ctx, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = function.native(&mut ctx).unwrap(); + // let function = Function::new(&mut store, &env, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); + // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = function.native(&mut store).unwrap(); // assert_eq!(typed_function.call().unwrap(), (1, 2, 3.0, 4.0)); } #[wasm_bindgen_test] fn function_outlives_instance() { - let store = Store::default(); - let mut ctx = Context::new(&store, ()); + let mut store = Store::default(); + let mut env = FunctionEnv::new(&mut store, ()); let wat = r#"(module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) @@ -421,18 +456,18 @@ mod js { let f = { let module = Module::new(&store, wat).unwrap(); - let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); + let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); let f = instance.exports.get_function("sum").unwrap(); assert_eq!( - f.call(&mut ctx, &[Val::I32(4), Val::I32(5)]).unwrap(), + f.call(&mut store, &[Val::I32(4), Val::I32(5)]).unwrap(), vec![Val::I32(9)].into_boxed_slice() ); f.clone() }; assert_eq!( - f.call(&mut ctx, &[Val::I32(4), Val::I32(5)]).unwrap(), + f.call(&mut store, &[Val::I32(4), Val::I32(5)]).unwrap(), vec![Val::I32(9)].into_boxed_slice() ); } diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs index c64d2e45431..c1d6102abe6 100644 --- a/lib/api/tests/js_instance.rs +++ b/lib/api/tests/js_instance.rs @@ -23,7 +23,7 @@ mod js { #[wasm_bindgen_test] fn test_exported_memory() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -41,24 +41,24 @@ mod js { .unwrap(); let import_object = imports! {}; - let mut ctx = Context::new(&store, ()); - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let mut env = FunctionEnv::new(&mut store, ()); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("mem").unwrap(); - assert!(memory.is_from_context(&ctx)); - assert_eq!(memory.ty(&ctx), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.size(&ctx), Pages(1)); - assert_eq!(memory.data_size(&ctx), 65536); - - memory.grow(&mut ctx, Pages(1)).unwrap(); - assert_eq!(memory.ty(&ctx), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.size(&ctx), Pages(2)); - assert_eq!(memory.data_size(&ctx), 65536 * 2); + assert!(memory.is_from_store(&store)); + assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); + assert_eq!(memory.size(&store), Pages(1)); + assert_eq!(memory.data_size(&store), 65536); + + memory.grow(&mut store, Pages(1)).unwrap(); + assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); + assert_eq!(memory.size(&store), Pages(2)); + assert_eq!(memory.data_size(&store), 65536 * 2); } #[wasm_bindgen_test] fn test_exported_function() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -81,22 +81,22 @@ mod js { .unwrap(); let import_object = imports! {}; - let mut ctx = Context::new(&store, ()); - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let mut env = FunctionEnv::new(&mut store, ()); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let get_magic = instance.exports.get_function("get_magic").unwrap(); assert_eq!( - get_magic.ty(&ctx).clone(), + get_magic.ty(&store).clone(), FunctionType::new(vec![], vec![Type::I32]) ); let expected = vec![Val::I32(42)].into_boxed_slice(); - assert_eq!(get_magic.call(&mut ctx, &[]).unwrap(), expected); + assert_eq!(get_magic.call(&mut store, &[]).unwrap(), expected); } #[wasm_bindgen_test] fn test_imported_function_dynamic() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -121,11 +121,11 @@ mod js { ))], }) .unwrap(); - let mut ctx = Context::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new(&mut ctx, imported_signature, |_env, args| { + let imported = Function::new(&mut store, &env, imported_signature, |_env, args| { log!("Calling `imported`..."); let result = args[0].unwrap_i32() * 2; log!("Result of `imported`: {:?}", result); @@ -137,19 +137,19 @@ mod js { "imported" => imported, } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(6)].into_boxed_slice(); - assert_eq!(exported.call(&mut ctx, &[Val::I32(3)]).unwrap(), expected); + assert_eq!(exported.call(&mut store, &[Val::I32(3)]).unwrap(), expected); } // We comment it for now because in old versions of Node, only single return values are supported // #[wasm_bindgen_test] // fn test_imported_function_dynamic_multivalue() { - // let store = Store::default(); + // let mut store = Store::default(); // let mut module = Module::new( // &store, // br#" @@ -207,7 +207,7 @@ mod js { #[wasm_bindgen_test] fn test_imported_function_dynamic_with_env() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -238,10 +238,10 @@ mod js { multiplier: i32, } - let mut ctx = Context::new(&store, Env { multiplier: 3 }); + let mut env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new(&mut ctx, &imported_signature, |ctx, args| { + let imported = Function::new(&mut store, &env, &imported_signature, |ctx, args| { log!("Calling `imported`..."); let result = args[0].unwrap_i32() * ctx.data().multiplier; log!("Result of `imported`: {:?}", result); @@ -253,17 +253,17 @@ mod js { "imported" => imported, } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(9)].into_boxed_slice(); - assert_eq!(exported.call(&mut ctx, &[Val::I32(3)]), Ok(expected)); + assert_eq!(exported.call(&mut store, &[Val::I32(3)]), Ok(expected)); } #[wasm_bindgen_test] fn test_imported_function_native() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -289,29 +289,29 @@ mod js { }) .unwrap(); - fn imported_fn(_: ContextMut<'_, ()>, arg: u32) -> u32 { + fn imported_fn(_: FunctionEnvMut<'_, ()>, arg: u32) -> u32 { return arg + 1; } - let mut ctx = Context::new(&store, ()); - let imported = Function::new_native(&mut ctx, imported_fn); + let mut env = FunctionEnv::new(&mut store, ()); + let imported = Function::new_native(&mut store, &env, imported_fn); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(5)].into_boxed_slice(); - assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] fn test_imported_function_native_with_env() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -342,33 +342,33 @@ mod js { multiplier: u32, } - fn imported_fn(ctx: ContextMut<'_, Env>, arg: u32) -> u32 { + fn imported_fn(ctx: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { log!("inside imported_fn: ctx.data is {:?}", ctx.data()); - // log!("inside call id is {:?}", ctx.as_context_ref().objects().id); + // log!("inside call id is {:?}", ctx.as_store_ref().objects().id); return ctx.data().multiplier * arg; } - let mut ctx = Context::new(&store, Env { multiplier: 3 }); + let mut env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - let imported = Function::new_native(&mut ctx, imported_fn); + let imported = Function::new_native(&mut store, &env, imported_fn); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let exported = instance.exports.get_function("exported").unwrap(); let expected = vec![Val::I32(12)].into_boxed_slice(); - ctx.data_mut().multiplier = 3; - assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); + env.as_mut(&mut store).multiplier = 3; + assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] fn test_imported_function_native_with_wasmer_env() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -401,76 +401,79 @@ mod js { memory: Option, } - fn imported_fn(ctx: ContextMut<'_, Env>, arg: u32) -> u32 { + fn imported_fn(ctx: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { let memory: &Memory = ctx.data().memory.as_ref().unwrap(); let memory_val = memory.uint8view(&ctx).get_index(0); return (memory_val as u32) * ctx.data().multiplier * arg; } - let mut ctx = Context::new( - &store, + let mut env = FunctionEnv::new( + &mut store, Env { multiplier: 3, memory: None, }, ); - let imported = Function::new_native(&mut ctx, imported_fn); + let imported = Function::new_native(&mut store, &env, imported_fn); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.data_size(&ctx), 65536); - let memory_val = memory.uint8view(&ctx).get_index(0); + assert_eq!(memory.data_size(&store), 65536); + let memory_val = memory.uint8view(&store).get_index(0); assert_eq!(memory_val, 0); - memory.uint8view(&ctx).set_index(0, 2); - let memory_val = memory.uint8view(&ctx).get_index(0); + memory.uint8view(&store).set_index(0, 2); + let memory_val = memory.uint8view(&store).get_index(0); assert_eq!(memory_val, 2); - ctx.data_mut().memory = Some(memory.clone()); + env.as_mut(&mut store).memory = Some(memory.clone()); let exported = instance.exports.get_function("exported").unwrap(); // It works with the provided memory let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.uint8view(&ctx).set_index(0, 3); + memory.uint8view(&store).set_index(0, 3); let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] fn test_unit_native_function_env() { - let store = Store::default(); + let mut store = Store::default(); #[derive(Clone)] struct Env { multiplier: u32, } - let mut ctx = Context::new(&store, Env { multiplier: 3 }); + let mut env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - fn imported_fn(ctx: ContextMut<'_, Env>, args: &[Val]) -> Result, RuntimeError> { + fn imported_fn( + ctx: FunctionEnvMut<'_, Env>, + args: &[Val], + ) -> Result, RuntimeError> { let value = ctx.data().multiplier * args[0].unwrap_i32() as u32; return Ok(vec![Val::I32(value as _)]); } let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new(&mut ctx, imported_signature, imported_fn); + let imported = Function::new(&mut store, &env, imported_signature, imported_fn); let expected = vec![Val::I32(12)].into_boxed_slice(); - assert_eq!(imported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); + assert_eq!(imported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] fn test_imported_function_with_wasmer_env() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -503,15 +506,18 @@ mod js { memory: Option, } - fn imported_fn(ctx: ContextMut<'_, Env>, args: &[Val]) -> Result, RuntimeError> { + fn imported_fn( + ctx: FunctionEnvMut<'_, Env>, + args: &[Val], + ) -> Result, RuntimeError> { let memory: &Memory = ctx.data().memory.as_ref().unwrap(); let memory_val = memory.uint8view(&ctx).get_index(0); let value = (memory_val as u32) * ctx.data().multiplier * args[0].unwrap_i32() as u32; return Ok(vec![Val::I32(value as _)]); } - let mut ctx = Context::new( - &store, + let mut env = FunctionEnv::new( + &mut store, Env { multiplier: 3, memory: None, @@ -519,41 +525,41 @@ mod js { ); let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new(&mut ctx, imported_signature, imported_fn); + let imported = Function::new(&mut store, &env, imported_signature, imported_fn); let import_object = imports! { "env" => { "imported" => imported, } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.data_size(&ctx), 65536); - let memory_val = memory.uint8view(&ctx).get_index(0); + assert_eq!(memory.data_size(&store), 65536); + let memory_val = memory.uint8view(&store).get_index(0); assert_eq!(memory_val, 0); - memory.uint8view(&ctx).set_index(0, 2); - let memory_val = memory.uint8view(&ctx).get_index(0); + memory.uint8view(&store).set_index(0, 2); + let memory_val = memory.uint8view(&store).get_index(0); assert_eq!(memory_val, 2); - ctx.data_mut().memory = Some(memory.clone()); + env.as_mut(&mut store).memory = Some(memory.clone()); let exported = instance.exports.get_function("exported").unwrap(); // It works with the provided memory let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); // It works if we update the memory - memory.uint8view(&ctx).set_index(0, 3); + memory.uint8view(&store).set_index(0, 3); let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&mut ctx, &[Val::I32(4)]), Ok(expected)); + assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); } #[wasm_bindgen_test] fn test_imported_exported_global() { - let store = Store::default(); + let mut store = Store::default(); let mut module = Module::new( &store, br#" @@ -579,39 +585,39 @@ mod js { ], }) .unwrap(); - let mut ctx = Context::new(&store, ()); - let global = Global::new_mut(&mut ctx, Value::I32(0)); + let mut env = FunctionEnv::new(&mut store, ()); + let global = Global::new_mut(&mut store, Value::I32(0)); let import_object = imports! { "" => { "global" => global.clone() } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let get_global = instance.exports.get_function("getGlobal").unwrap(); assert_eq!( - get_global.call(&mut ctx, &[]), + get_global.call(&mut store, &[]), Ok(vec![Val::I32(0)].into_boxed_slice()) ); - global.set(&mut ctx, Value::I32(42)).unwrap(); + global.set(&mut store, Value::I32(42)).unwrap(); assert_eq!( - get_global.call(&mut ctx, &[]), + get_global.call(&mut store, &[]), Ok(vec![Val::I32(42)].into_boxed_slice()) ); let inc_global = instance.exports.get_function("incGlobal").unwrap(); - inc_global.call(&mut ctx, &[]).unwrap(); + inc_global.call(&mut store, &[]).unwrap(); assert_eq!( - get_global.call(&mut ctx, &[]), + get_global.call(&mut store, &[]), Ok(vec![Val::I32(43)].into_boxed_slice()) ); - assert_eq!(global.get(&ctx), Val::I32(43)); + assert_eq!(global.get(&store), Val::I32(43)); } #[wasm_bindgen_test] fn test_native_function() { - let store = Store::default(); + let mut store = Store::default(); let module = Module::new( &store, br#"(module @@ -623,30 +629,30 @@ mod js { ) .unwrap(); - fn sum(_: ContextMut<'_, ()>, a: i32, b: i32) -> i32 { + fn sum(_: FunctionEnvMut<'_, ()>, a: i32, b: i32) -> i32 { a + b } - let mut ctx = Context::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! { "env" => { - "sum" => Function::new_native(&mut ctx, sum), + "sum" => Function::new_native(&mut store, &env, sum), } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let add_one: TypedFunction = instance .exports - .get_typed_function(&ctx, "add_one") + .get_typed_function(&mut store, "add_one") .unwrap(); - assert_eq!(add_one.call(&mut ctx, 1), Ok(2)); + assert_eq!(add_one.call(&mut store, 1), Ok(2)); } #[wasm_bindgen_test] fn test_panic() { - let store = Store::default(); + let mut store = Store::default(); let module = Module::new( &store, br#" @@ -664,30 +670,32 @@ mod js { ) .unwrap(); - fn early_exit(_: ContextMut<'_, ()>) { + fn early_exit(_: FunctionEnvMut<'_, ()>) { panic!("Do panic") } - let mut ctx = Context::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! { "env" => { - "early_exit" => Function::new_native(&mut ctx, early_exit), + "early_exit" => Function::new_native(&mut store, &env, early_exit), } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - let run_func: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function(&ctx, "run").unwrap(); + let run_func: TypedFunction<(i32, i32), i32> = instance + .exports + .get_typed_function(&mut store, "run") + .unwrap(); assert!( - run_func.call(&mut ctx, 1, 7).is_err(), + run_func.call(&mut store, 1, 7).is_err(), "Expected early termination", ); let run_func = instance.exports.get_function("run").unwrap(); assert!( run_func - .call(&mut ctx, &[Val::I32(1), Val::I32(7)]) + .call(&mut store, &[Val::I32(1), Val::I32(7)]) .is_err(), "Expected early termination", ); @@ -695,7 +703,7 @@ mod js { #[wasm_bindgen_test] fn test_custom_error() { - let store = Store::default(); + let mut store = Store::default(); let module = Module::new( &store, br#" @@ -713,7 +721,7 @@ mod js { ) .unwrap(); - let mut ctx = Context::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); use std::fmt; @@ -728,17 +736,17 @@ mod js { impl std::error::Error for ExitCode {} - fn early_exit(_: ContextMut<'_, ()>) -> Result<(), ExitCode> { + fn early_exit(_: FunctionEnvMut<'_, ()>) -> Result<(), ExitCode> { Err(ExitCode(1)) } let import_object = imports! { "env" => { - "early_exit" => Function::new_native(&mut ctx, early_exit), + "early_exit" => Function::new_native(&mut store, &env, early_exit), } }; - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); fn test_result(result: Result) { match result { @@ -763,17 +771,19 @@ mod js { } } - let run_func: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function(&ctx, "run").unwrap(); - test_result(run_func.call(&mut ctx, 1, 7)); + let run_func: TypedFunction<(i32, i32), i32> = instance + .exports + .get_typed_function(&mut store, "run") + .unwrap(); + test_result(run_func.call(&mut store, 1, 7)); let run_func = instance.exports.get_function("run").unwrap(); - test_result(run_func.call(&mut ctx, &[Val::I32(1), Val::I32(7)])); + test_result(run_func.call(&mut store, &[Val::I32(1), Val::I32(7)])); } #[wasm_bindgen_test] fn test_start_function_fails() { - let store = Store::default(); + let mut store = Store::default(); let module = Module::new( &store, br#" @@ -792,8 +802,8 @@ mod js { .unwrap(); let import_object = imports! {}; - let mut ctx = Context::new(&store, ()); - let result = Instance::new(&mut ctx, &module, &import_object); + let mut env = FunctionEnv::new(&mut store, ()); + let result = Instance::new(&mut store, &module, &import_object); let err = result.unwrap_err(); assert!(format!("{:?}", err).contains("zero")) } diff --git a/lib/api/tests/js_module.rs b/lib/api/tests/js_module.rs index a1c46e40a1a..3155e7e5f3b 100644 --- a/lib/api/tests/js_module.rs +++ b/lib/api/tests/js_module.rs @@ -6,7 +6,7 @@ mod js { #[wasm_bindgen_test] fn module_get_name() { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module)"#; let module = Module::new(&store, wat).unwrap(); assert_eq!(module.name(), None); @@ -14,7 +14,7 @@ mod js { #[wasm_bindgen_test] fn module_set_name() { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module $name)"#; let mut module = Module::new(&store, wat).unwrap(); @@ -32,12 +32,11 @@ mod js { let js_bytes = unsafe { Uint8Array::view(&binary) }; let js_module = WebAssembly::Module::new(&js_bytes.into()).unwrap(); let module: Module = js_module.into(); - assert_eq!(module.store(), &Store::default()); } #[wasm_bindgen_test] fn imports() { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (import "host" "func" (func)) (import "host" "memory" (memory 1)) @@ -108,7 +107,7 @@ mod js { #[wasm_bindgen_test] fn exports() { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (func (export "func") nop) (memory (export "memory") 2) @@ -182,7 +181,7 @@ mod js { // #[wasm_bindgen_test] // fn calling_host_functions_with_negative_values_works() { - // let store = Store::default(); + // let mut store = Store::default(); // let wat = r#"(module // (import "host" "host_func1" (func (param i64))) // (import "host" "host_func2" (func (param i32))) diff --git a/lib/api/tests/sys_externals.rs b/lib/api/tests/sys_externals.rs index d23ab50eeed..26be6969193 100644 --- a/lib/api/tests/sys_externals.rs +++ b/lib/api/tests/sys_externals.rs @@ -1,25 +1,24 @@ #[cfg(feature = "sys")] mod sys { use anyhow::Result; - use wasmer::Context as WasmerContext; + use wasmer::FunctionEnv; use wasmer::*; #[test] fn global_new() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let global = Global::new(&mut ctx, Value::I32(10)); + let mut store = Store::default(); + let global = Global::new(&mut store, Value::I32(10)); assert_eq!( - global.ty(&mut ctx), + global.ty(&mut store), GlobalType { ty: Type::I32, mutability: Mutability::Const } ); - let global_mut = Global::new_mut(&mut ctx, Value::I32(10)); + let global_mut = Global::new_mut(&mut store, Value::I32(10)); assert_eq!( - global_mut.ty(&mut ctx), + global_mut.ty(&mut store), GlobalType { ty: Type::I32, mutability: Mutability::Var @@ -31,51 +30,49 @@ mod sys { #[test] fn global_get() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let global_i32 = Global::new(&mut ctx, Value::I32(10)); - assert_eq!(global_i32.get(&mut ctx), Value::I32(10)); - let global_i64 = Global::new(&mut ctx, Value::I64(20)); - assert_eq!(global_i64.get(&mut ctx), Value::I64(20)); - let global_f32 = Global::new(&mut ctx, Value::F32(10.0)); - assert_eq!(global_f32.get(&mut ctx), Value::F32(10.0)); - let global_f64 = Global::new(&mut ctx, Value::F64(20.0)); - assert_eq!(global_f64.get(&mut ctx), Value::F64(20.0)); + let mut store = Store::default(); + let global_i32 = Global::new(&mut store, Value::I32(10)); + assert_eq!(global_i32.get(&mut store), Value::I32(10)); + let global_i64 = Global::new(&mut store, Value::I64(20)); + assert_eq!(global_i64.get(&mut store), Value::I64(20)); + let global_f32 = Global::new(&mut store, Value::F32(10.0)); + assert_eq!(global_f32.get(&mut store), Value::F32(10.0)); + let global_f64 = Global::new(&mut store, Value::F64(20.0)); + assert_eq!(global_f64.get(&mut store), Value::F64(20.0)); Ok(()) } #[test] fn global_set() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let global_i32 = Global::new(&mut ctx, Value::I32(10)); + let mut store = Store::default(); + let global_i32 = Global::new(&mut store, Value::I32(10)); // Set on a constant should error - assert!(global_i32.set(&mut ctx, Value::I32(20)).is_err()); + assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); - let global_i32_mut = Global::new_mut(&mut ctx, Value::I32(10)); + let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); // Set on different type should error - assert!(global_i32_mut.set(&mut ctx, Value::I64(20)).is_err()); + assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); // Set on same type should succeed - global_i32_mut.set(&mut ctx, Value::I32(20))?; - assert_eq!(global_i32_mut.get(&mut ctx), Value::I32(20)); + global_i32_mut.set(&mut store, Value::I32(20))?; + assert_eq!(global_i32_mut.get(&mut store), Value::I32(20)); Ok(()) } #[test] fn table_new() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: None, }; - let f = Function::new_native(&mut ctx, |_ctx: ContextMut<()>| {}); - let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(table.ty(&mut ctx), table_type); + let env = FunctionEnv::new(&mut store, ()); + let f = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>| {}); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; + assert_eq!(table.ty(&mut store), table_type); // Anyrefs not yet supported // let table_type = TableType { @@ -92,17 +89,19 @@ mod sys { #[test] #[ignore] fn table_get() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: Some(1), }; - let f = Function::new_native(&mut ctx, |_ctx: ContextMut<()>, num: i32| num + 1); - let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(table.ty(&mut ctx), table_type); - let _elem = table.get(&mut ctx, 0).unwrap(); + let f = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>, num: i32| { + num + 1 + }); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; + assert_eq!(table.ty(&mut store), table_type); + let _elem = table.get(&mut store, 0).unwrap(); // assert_eq!(elem.funcref().unwrap(), f); Ok(()) } @@ -116,21 +115,23 @@ mod sys { #[test] fn table_grow() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); let table_type = TableType { ty: Type::FuncRef, minimum: 0, maximum: Some(10), }; - let f = Function::new_native(&mut ctx, |_ctx: ContextMut<()>, num: i32| num + 1); - let table = Table::new(&mut ctx, table_type, Value::FuncRef(Some(f.clone())))?; + let f = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>, num: i32| { + num + 1 + }); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone())))?; // Growing to a bigger maximum should return None - let old_len = table.grow(&mut ctx, 12, Value::FuncRef(Some(f.clone()))); + let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); assert!(old_len.is_err()); // Growing to a bigger maximum should return None - let old_len = table.grow(&mut ctx, 5, Value::FuncRef(Some(f)))?; + let old_len = table.grow(&mut store, 5, Value::FuncRef(Some(f)))?; assert_eq!(old_len, 0); Ok(()) @@ -145,32 +146,30 @@ mod sys { #[test] fn memory_new() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); let memory_type = MemoryType { shared: false, minimum: Pages(0), maximum: Some(Pages(10)), }; - let memory = Memory::new(&mut ctx, memory_type)?; - assert_eq!(memory.size(&mut ctx), Pages(0)); - assert_eq!(memory.ty(&mut ctx), memory_type); + let memory = Memory::new(&mut store, memory_type)?; + assert_eq!(memory.size(&mut store), Pages(0)); + assert_eq!(memory.ty(&mut store), memory_type); Ok(()) } #[test] fn memory_grow() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&mut ctx, desc)?; - assert_eq!(memory.size(&mut ctx), Pages(10)); + let memory = Memory::new(&mut store, desc)?; + assert_eq!(memory.size(&mut store), Pages(10)); - let result = memory.grow(&mut ctx, Pages(2)).unwrap(); + let result = memory.grow(&mut store, Pages(2)).unwrap(); assert_eq!(result, Pages(10)); - assert_eq!(memory.size(&mut ctx), Pages(12)); + assert_eq!(memory.size(&mut store), Pages(12)); - let result = memory.grow(&mut ctx, Pages(10)); + let result = memory.grow(&mut store, Pages(10)); assert_eq!( result, Err(MemoryError::CouldNotGrow { @@ -180,7 +179,7 @@ mod sys { ); let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); - let bad_result = Memory::new(&mut ctx, bad_desc); + let bad_result = Memory::new(&mut store, bad_desc); assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); @@ -189,37 +188,41 @@ mod sys { #[test] fn function_new() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| {}); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); + let function = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>| {}); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![], vec![]) ); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, _a: i32| {}); + let function = + Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>, _a: i32| {}); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![Type::I32], vec![]) ); let function = Function::new_native( - &mut ctx, - |_ctx: ContextMut<_>, _a: i32, _b: i64, _c: f32, _d: f64| {}, + &mut store, + &env, + |_ctx: FunctionEnvMut<()>, _a: i32, _b: i64, _c: f32, _d: f64| {}, ); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| -> i32 { 1 }); + let function = + Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>| -> i32 { 1 }); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![], vec![Type::I32]) ); - let function = - Function::new_native(&mut ctx, |_ctx: ContextMut<_>| -> (i32, i64, f32, f64) { - (1, 2, 3.0, 4.0) - }); + let function = Function::new_native( + &mut store, + &env, + |_ctx: FunctionEnvMut<()>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + ); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); Ok(()) @@ -227,41 +230,45 @@ mod sys { #[test] fn function_new_env() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; - let mut ctx = WasmerContext::new(&store, my_env); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut| {}); + let env = FunctionEnv::new(&mut store, my_env); + let function = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut| {}); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![], vec![]) ); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut, _a: i32| {}); + let function = + Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut, _a: i32| {}); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![Type::I32], vec![]) ); let function = Function::new_native( - &mut ctx, - |_ctx: ContextMut, _a: i32, _b: i64, _c: f32, _d: f64| {}, + &mut store, + &env, + |_ctx: FunctionEnvMut, _a: i32, _b: i64, _c: f32, _d: f64| {}, ); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut| -> i32 { 1 }); + let function = + Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut| -> i32 { 1 }); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![], vec![Type::I32]) ); let function = Function::new_native( - &mut ctx, - |_ctx: ContextMut| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + &mut store, + &env, + |_ctx: FunctionEnvMut| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, ); assert_eq!( - function.ty(&mut ctx).clone(), + function.ty(&mut store).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) ); Ok(()) @@ -269,58 +276,64 @@ mod sys { #[test] fn function_new_dynamic() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, function_type, - |_ctx: ContextMut<()>, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut<()>, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).params(), [Type::V128]); + assert_eq!(function.ty(&mut store).params(), [Type::V128]); assert_eq!( - function.ty(&mut ctx).results(), + function.ty(&mut store).results(), [Type::I32, Type::F32, Type::F64] ); @@ -329,193 +342,199 @@ mod sys { #[test] fn function_new_dynamic_env() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); #[derive(Clone)] struct MyEnv {} let my_env = MyEnv {}; - let mut ctx = WasmerContext::new(&store, my_env); + let env = FunctionEnv::new(&mut store, my_env); // Using &FunctionType signature let function_type = FunctionType::new(vec![], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, &function_type, - |_ctx: ContextMut, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).clone(), function_type); + assert_eq!(function.ty(&mut store).clone(), function_type); // Using array signature let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); let function = Function::new( - &mut ctx, + &mut store, + &env, function_type, - |_ctx: ContextMut, _values: &[Value]| unimplemented!(), + |_ctx: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); - assert_eq!(function.ty(&mut ctx).params(), [Type::V128]); + assert_eq!(function.ty(&mut store).params(), [Type::V128]); assert_eq!( - function.ty(&mut ctx).results(), + function.ty(&mut store).results(), [Type::I32, Type::F32, Type::F64] ); Ok(()) } - #[test] - fn native_function_works() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<()>| {}); - let native_function: TypedFunction<(), ()> = function.native(&mut ctx).unwrap(); - let result = native_function.call(&mut ctx); - assert!(result.is_ok()); - - let function = - Function::new_native(&mut ctx, |_ctx: ContextMut<()>, a: i32| -> i32 { a + 1 }); - let native_function: TypedFunction = function.native(&mut ctx).unwrap(); - assert_eq!(native_function.call(&mut ctx, 3).unwrap(), 4); - - fn rust_abi(_ctx: ContextMut<()>, a: i32, b: i64, c: f32, d: f64) -> u64 { - (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) - } - let function = Function::new_native(&mut ctx, rust_abi); - let native_function: TypedFunction<(i32, i64, f32, f64), u64> = - function.native(&mut ctx).unwrap(); - assert_eq!(native_function.call(&mut ctx, 8, 4, 1.5, 5.).unwrap(), 8415); - - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<()>| -> i32 { 1 }); - let native_function: TypedFunction<(), i32> = function.native(&mut ctx).unwrap(); - assert_eq!(native_function.call(&mut ctx).unwrap(), 1); - - let function = Function::new_native(&mut ctx, |_ctx: ContextMut<()>, _a: i32| {}); - let native_function: TypedFunction = function.native(&mut ctx).unwrap(); - assert!(native_function.call(&mut ctx, 4).is_ok()); - - let function = - Function::new_native(&mut ctx, |_ctx: ContextMut<()>| -> (i32, i64, f32, f64) { - (1, 2, 3.0, 4.0) - }); - let native_function: TypedFunction<(), (i32, i64, f32, f64)> = - function.native(&mut ctx).unwrap(); - assert_eq!(native_function.call(&mut ctx).unwrap(), (1, 2, 3.0, 4.0)); - - Ok(()) - } - - #[test] - fn function_outlives_instance() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let wat = r#"(module - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export "sum" (func $sum_f))) -"#; - - let f = { - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut ctx, &module, &imports! {})?; - let f: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function(&mut ctx, "sum")?; - - assert_eq!(f.call(&mut ctx, 4, 5)?, 9); - f - }; - - assert_eq!(f.call(&mut ctx, 4, 5)?, 9); - - Ok(()) - } - /* - #[test] - fn weak_instance_ref_externs_after_instance() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); - let wat = r#"(module - (memory (export "mem") 1) - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export "sum" (func $sum_f))) - "#; - - let f = { - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut ctx, &module, &imports! {})?; - let f: TypedFunction<(i32, i32), i32> = - instance.exports.get_with_generics_weak("sum")?; - - assert_eq!(f.call(&mut ctx, 4, 5)?, 9); - f - }; - - assert_eq!(f.call(&mut ctx, 4, 5)?, 9); - - Ok(()) - } - */ - #[test] - fn manually_generate_wasmer_env() -> Result<()> { - let store = Store::default(); - #[derive(Clone)] - struct MyEnv { - val: u32, - memory: Option, - } - - fn host_function(ctx: ContextMut, arg1: u32, arg2: u32) -> u32 { - ctx.data().val + arg1 + arg2 - } - - let mut env = MyEnv { - val: 5, - memory: None, - }; - let mut ctx = WasmerContext::new(&store, env); - - let result = host_function(ctx.as_context_mut(), 7, 9); - assert_eq!(result, 21); - - let memory = Memory::new(&mut ctx, MemoryType::new(0, None, false))?; - ctx.data_mut().memory = Some(memory); - - let result = host_function(ctx.as_context_mut(), 1, 2); - assert_eq!(result, 8); - - Ok(()) - } + // #[test] + // fn native_function_works() -> Result<()> { + // let mut store = Store::default(); + // let env = FunctionEnv::new(&mut store, ()); + // let function = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>| {}); + // let native_function: TypedFunction<(), ()> = function.native(&mut store).unwrap(); + // let result = native_function.call(&mut store); + // assert!(result.is_ok()); + + // let function = + // Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>, a: i32| -> i32 { a + 1 }); + // let native_function: TypedFunction = function.native(&mut store).unwrap(); + // assert_eq!(native_function.call(&mut store, 3).unwrap(), 4); + + // fn rust_abi(_ctx: FunctionEnvMut<()>, a: i32, b: i64, c: f32, d: f64) -> u64 { + // (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) + // } + // let function = Function::new_native(&mut store, &env, rust_abi); + // let native_function: TypedFunction<(i32, i64, f32, f64), u64> = + // function.native(&mut store).unwrap(); + // assert_eq!(native_function.call(&mut store, 8, 4, 1.5, 5.).unwrap(), 8415); + + // let function = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>| -> i32 { 1 }); + // let native_function: TypedFunction<(), i32> = function.native(&mut store).unwrap(); + // assert_eq!(native_function.call(&mut store).unwrap(), 1); + + // let function = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>, _a: i32| {}); + // let native_function: TypedFunction = function.native(&mut store).unwrap(); + // assert!(native_function.call(&mut store, 4).is_ok()); + + // let function = + // Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>| -> (i32, i64, f32, f64) { + // (1, 2, 3.0, 4.0) + // }); + // let native_function: TypedFunction<(), (i32, i64, f32, f64)> = + // function.native(&mut store).unwrap(); + // assert_eq!(native_function.call(&mut store).unwrap(), (1, 2, 3.0, 4.0)); + + // Ok(()) + // } + + // #[test] + // fn function_outlives_instance() -> Result<()> { + // let mut store = Store::default(); + // let env = FunctionEnv::new(&mut store, ()); + // let wat = r#"(module + // (type $sum_t (func (param i32 i32) (result i32))) + // (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) + // local.get $x + // local.get $y + // i32.add) + // (export "sum" (func $sum_f))) + // "#; + + // let f = { + // let module = Module::new(&store, wat)?; + // let instance = Instance::new(&mut store, &module, &imports! {})?; + // let f: TypedFunction<(i32, i32), i32> = + // instance.exports.get_typed_function(&mut store, "sum")?; + + // assert_eq!(f.call(&mut store, 4, 5)?, 9); + // f + // }; + + // assert_eq!(f.call(&mut store, 4, 5)?, 9); + + // Ok(()) + // } + // /* + // #[test] + // fn weak_instance_ref_externs_after_instance() -> Result<()> { + // let mut store = Store::default(); + // let env = FunctionEnv::new(&mut store, ()); + // let wat = r#"(module + // (memory (export "mem") 1) + // (type $sum_t (func (param i32 i32) (result i32))) + // (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) + // local.get $x + // local.get $y + // i32.add) + // (export "sum" (func $sum_f))) + // "#; + + // let f = { + // let module = Module::new(&store, wat)?; + // let instance = Instance::new(&mut store, &module, &imports! {})?; + // let f: TypedFunction<(i32, i32), i32> = + // instance.exports.get_with_generics_weak("sum")?; + + // assert_eq!(f.call(&mut store, 4, 5)?, 9); + // f + // }; + + // assert_eq!(f.call(&mut store, 4, 5)?, 9); + + // Ok(()) + // } + // */ + // #[test] + // fn manually_generate_wasmer_env() -> Result<()> { + // let mut store = Store::default(); + // #[derive(Clone)] + // struct MyEnv { + // val: u32, + // memory: Option, + // } + + // fn host_function(ctx: FunctionEnvMut, arg1: u32, arg2: u32) -> u32 { + // ctx.data().val + arg1 + arg2 + // } + + // let mut env = MyEnv { + // val: 5, + // memory: None, + // }; + // let env = FunctionEnv::new(&mut store, env); + + // let result = host_function(ctx.as_context_mut(), 7, 9); + // assert_eq!(result, 21); + + // let memory = Memory::new(&mut store, MemoryType::new(0, None, false))?; + // ctx.as_mut(&mut store).memory = Some(memory); + + // let result = host_function(ctx.as_context_mut(), 1, 2); + // assert_eq!(result, 8); + + // Ok(()) + // } } diff --git a/lib/api/tests/sys_instance.rs b/lib/api/tests/sys_instance.rs index d3eac9255eb..234bffe93b4 100644 --- a/lib/api/tests/sys_instance.rs +++ b/lib/api/tests/sys_instance.rs @@ -1,13 +1,12 @@ #[cfg(feature = "sys")] mod sys { use anyhow::Result; - use wasmer::Context as WasmerContext; + use wasmer::FunctionEnv; use wasmer::*; #[test] fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); let module = Module::new( &store, " @@ -22,7 +21,7 @@ mod sys { )?; let imports = Imports::new(); - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; let instance2 = instance.clone(); let instance3 = instance.clone(); @@ -35,7 +34,7 @@ mod sys { // All instances have been dropped, but `sum` continues to work! assert_eq!( - sum.call(&mut ctx, &[Value::I32(1), Value::I32(2)])? + sum.call(&mut store, &[Value::I32(1), Value::I32(2)])? .into_vec(), vec![Value::I32(3)], ); @@ -45,24 +44,31 @@ mod sys { #[test] fn unit_native_function_env() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); + #[derive(Clone)] struct Env { multiplier: u32, } - fn imported_fn(ctx: ContextMut, args: &[Value]) -> Result, RuntimeError> { + fn imported_fn( + ctx: FunctionEnvMut, + args: &[Value], + ) -> Result, RuntimeError> { let value = ctx.data().multiplier * args[0].unwrap_i32() as u32; Ok(vec![Value::I32(value as _)]) } + // We create the environment let env = Env { multiplier: 3 }; - let mut ctx = WasmerContext::new(&store, env); + // We move the environment to the store, so it can be used by the `Function` + let env = FunctionEnv::new(&mut store, env); + let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new(&mut ctx, imported_signature, imported_fn); + let imported = Function::new(&mut store, &env, imported_signature, imported_fn); let expected = vec![Value::I32(12)].into_boxed_slice(); - let result = imported.call(&mut ctx, &[Value::I32(4)])?; + let result = imported.call(&mut store, &[Value::I32(4)])?; assert_eq!(result, expected); Ok(()) diff --git a/lib/api/tests/sys_module.rs b/lib/api/tests/sys_module.rs index 7b5cf58f290..551e8aaae70 100644 --- a/lib/api/tests/sys_module.rs +++ b/lib/api/tests/sys_module.rs @@ -1,7 +1,7 @@ #[cfg(feature = "sys")] mod sys { use anyhow::Result; - use wasmer::Context as WasmerContext; + use wasmer::FunctionEnv; use wasmer::*; #[test] @@ -162,7 +162,7 @@ mod sys { #[test] fn calling_host_functions_with_negative_values_works() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (import "host" "host_func1" (func (param i64))) (import "host" "host_func2" (func (param i32))) @@ -191,78 +191,78 @@ mod sys { (call 7 (i32.const -1))) )"#; let module = Module::new(&store, wat)?; - let mut ctx = WasmerContext::new(&store, ()); + let env = FunctionEnv::new(&mut store, ()); let imports = imports! { "host" => { - "host_func1" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u64| { + "host_func1" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: u64| { println!("host_func1: Found number {}", p); assert_eq!(p, u64::max_value()); }), - "host_func2" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u32| { + "host_func2" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: u32| { println!("host_func2: Found number {}", p); assert_eq!(p, u32::max_value()); }), - "host_func3" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i64| { + "host_func3" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: i64| { println!("host_func3: Found number {}", p); assert_eq!(p, -1); }), - "host_func4" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i32| { + "host_func4" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: i32| { println!("host_func4: Found number {}", p); assert_eq!(p, -1); }), - "host_func5" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i16| { + "host_func5" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: i16| { println!("host_func5: Found number {}", p); assert_eq!(p, -1); }), - "host_func6" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u16| { + "host_func6" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: u16| { println!("host_func6: Found number {}", p); assert_eq!(p, u16::max_value()); }), - "host_func7" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: i8| { + "host_func7" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: i8| { println!("host_func7: Found number {}", p); assert_eq!(p, -1); }), - "host_func8" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, p: u8| { + "host_func8" => Function::new_native(&mut store, &env,|_ctx: FunctionEnvMut<()>, p: u8| { println!("host_func8: Found number {}", p); assert_eq!(p, u8::max_value()); }), } }; - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; let f1: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func1")?; + .get_typed_function(&mut store, "call_host_func1")?; let f2: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func2")?; + .get_typed_function(&mut store, "call_host_func2")?; let f3: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func3")?; + .get_typed_function(&mut store, "call_host_func3")?; let f4: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func4")?; + .get_typed_function(&mut store, "call_host_func4")?; let f5: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func5")?; + .get_typed_function(&mut store, "call_host_func5")?; let f6: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func6")?; + .get_typed_function(&mut store, "call_host_func6")?; let f7: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func7")?; + .get_typed_function(&mut store, "call_host_func7")?; let f8: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut ctx, "call_host_func8")?; + .get_typed_function(&mut store, "call_host_func8")?; - f1.call(&mut ctx)?; - f2.call(&mut ctx)?; - f3.call(&mut ctx)?; - f4.call(&mut ctx)?; - f5.call(&mut ctx)?; - f6.call(&mut ctx)?; - f7.call(&mut ctx)?; - f8.call(&mut ctx)?; + f1.call(&mut store)?; + f2.call(&mut store)?; + f3.call(&mut store)?; + f4.call(&mut store)?; + f5.call(&mut store)?; + f6.call(&mut store)?; + f7.call(&mut store)?; + f8.call(&mut store)?; Ok(()) } diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs index c28ab852e47..b31b32b4b78 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/sys_reference_types.rs @@ -1,15 +1,14 @@ #[cfg(feature = "sys")] mod sys { use anyhow::Result; - use std::collections::HashMap; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; - use wasmer::Context as WasmerContext; + use wasmer::FunctionEnv; use wasmer::*; #[test] fn func_ref_passed_and_returned() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (import "env" "func_ref_identity" (func (param funcref) (result funcref))) (type $ret_i32_ty (func (result i32))) @@ -25,33 +24,37 @@ mod sys { #[derive(Clone, Debug)] pub struct Env(Arc); let env = Env(Arc::new(AtomicBool::new(false))); - let mut ctx = WasmerContext::new(&store, env); + let env = FunctionEnv::new(&mut store, env); let imports = imports! { "env" => { - "func_ref_identity" => Function::new(&mut ctx, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |_ctx: ContextMut, values: &[Value]| -> Result, _> { + "func_ref_identity" => Function::new(&mut store, &env, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |_ctx: FunctionEnvMut, values: &[Value]| -> Result, _> { Ok(vec![values[0].clone()]) }) }, }; - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; let f: &Function = instance.exports.get_function("run")?; - let results = f.call(&mut ctx, &[]).unwrap(); + let results = f.call(&mut store, &[]).unwrap(); if let Value::FuncRef(fr) = &results[0] { assert!(fr.is_none()); } else { panic!("funcref not found!"); } - let func_to_call = Function::new_native(&mut ctx, |mut ctx: ContextMut| -> i32 { - ctx.data_mut().0.store(true, Ordering::SeqCst); - 343 - }); + let func_to_call = + Function::new_native(&mut store, &env, |mut ctx: FunctionEnvMut| -> i32 { + ctx.data_mut().0.store(true, Ordering::SeqCst); + 343 + }); let call_set_value: &Function = instance.exports.get_function("call_set_value")?; let results: Box<[Value]> = - call_set_value.call(&mut ctx, &[Value::FuncRef(Some(func_to_call))])?; - assert!(ctx.data().0.load(Ordering::SeqCst)); + call_set_value.call(&mut store, &[Value::FuncRef(Some(func_to_call))])?; + assert!(env + .as_mut(&mut store.as_store_mut()) + .0 + .load(Ordering::SeqCst)); assert_eq!(&*results, &[Value::I32(343)]); Ok(()) @@ -59,7 +62,7 @@ mod sys { #[test] fn func_ref_passed_and_called() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (func $func_ref_call (import "env" "func_ref_call") (param funcref) (result i32)) (type $ret_i32_ty (func (result i32))) @@ -78,9 +81,9 @@ mod sys { (call $func_ref_call (ref.func $product))) )"#; let module = Module::new(&store, wat)?; - let mut ctx = WasmerContext::new(&store, ()); + let env = FunctionEnv::new(&mut store, ()); fn func_ref_call( - mut ctx: ContextMut<()>, + mut ctx: FunctionEnvMut<()>, values: &[Value], ) -> Result, RuntimeError> { // TODO: look into `Box<[Value]>` being returned breakage @@ -92,47 +95,46 @@ mod sys { let imports = imports! { "env" => { "func_ref_call" => Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new([Type::FuncRef], [Type::I32]), func_ref_call ), - // TODO(reftypes): this should work - /* - "func_ref_call_native" => Function::new_native(&store, |f: Function| -> Result { - let f: TypedFunction::<(i32, i32), i32> = f.native()?; - f.call(7, 9) - }) - */ + // "func_ref_call_native" => Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>, f: Function| -> Result { + // let f: TypedFunction::<(i32, i32), i32> = f.native(&mut store)?; + // f.call(&mut store, 7, 9) + // }) }, }; - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; { - fn sum(_ctx: ContextMut<()>, a: i32, b: i32) -> i32 { + fn sum(_ctx: FunctionEnvMut<()>, a: i32, b: i32) -> i32 { a + b } - let sum_func = Function::new_native(&mut ctx, sum); + let sum_func = Function::new_native(&mut store, &env, sum); let call_func: &Function = instance.exports.get_function("call_func")?; - let result = call_func.call(&mut ctx, &[Value::FuncRef(Some(sum_func))])?; + let result = call_func.call(&mut store, &[Value::FuncRef(Some(sum_func))])?; assert_eq!(result[0].unwrap_i32(), 16); } { let f: TypedFunction<(), i32> = instance .exports - .get_typed_function(&mut ctx, "call_host_func_with_wasm_func")?; - let result = f.call(&mut ctx)?; + .get_typed_function(&mut store, "call_host_func_with_wasm_func")?; + let result = f.call(&mut store)?; assert_eq!(result, 63); } Ok(()) } + /* #[test] fn extern_ref_passed_and_returned() -> Result<()> { - let store = Store::default(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = Store::default(); + let env = FunctionEnv::new(&mut store, ()); let wat = r#"(module (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) @@ -149,15 +151,16 @@ mod sys { (call $get_new_extern_ref_native)) )"#; let module = Module::new(&store, wat)?; + let env = FunctionEnv::new(&mut store, ()); let imports = imports! { "env" => { - "extern_ref_identity" => Function::new(&mut ctx, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |_ctx, values| -> Result, _> { + "extern_ref_identity" => Function::new(&mut store, &env, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |_ctx, values| -> Result, _> { Ok(vec![values[0].clone()]) }), - "extern_ref_identity_native" => Function::new_native(&mut ctx, |_ctx: ContextMut<()>, er: ExternRef| -> ExternRef { + "extern_ref_identity_native" => Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<()>, er: ExternRef| -> ExternRef { er }), - "get_new_extern_ref" => Function::new(&mut ctx, FunctionType::new([], [Type::ExternRef]), |_ctx, _| -> Result, _> { + "get_new_extern_ref" => Function::new(&mut store, &env, FunctionType::new([], [Type::ExternRef]), |_ctx, _| -> Result, _> { let inner = [("hello".to_string(), "world".to_string()), ("color".to_string(), "orange".to_string())] @@ -167,7 +170,7 @@ mod sys { let new_extern_ref = ExternRef::new(&mut ctx, inner); Ok(vec![Value::ExternRef(new_extern_ref)]) }), - "get_new_extern_ref_native" => Function::new_native(&mut ctx, |_ctx| -> ExternRef { + "get_new_extern_ref_native" => Function::new_native(&mut store, &env,|_ctx| -> ExternRef { let inner = [("hello".to_string(), "world".to_string()), ("color".to_string(), "orange".to_string())] @@ -217,11 +220,11 @@ mod sys { Ok(()) } - #[test] + #[test] // TODO(reftypes): reenable this test #[ignore] fn extern_ref_ref_counting_basic() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (func (export "drop") (param $er externref) (result) (drop (local.get $er))) @@ -241,7 +244,7 @@ mod sys { #[test] fn refs_in_globals() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (global $er_global (export "er_global") (mut externref) (ref.null extern)) (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) @@ -306,7 +309,7 @@ mod sys { #[test] fn extern_ref_ref_counting_table_basic() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (global $global (export "global") (mut externref) (ref.null extern)) (table $table (export "table") 4 4 externref) @@ -348,7 +351,7 @@ mod sys { // TODO(reftypes): reenable this test #[ignore] fn extern_ref_ref_counting_global_basic() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (global $global (export "global") (mut externref) (ref.null extern)) (func $get_from_global (export "get_from_global") (result externref) @@ -379,7 +382,7 @@ mod sys { // TODO(reftypes): reenable this test #[ignore] fn extern_ref_ref_counting_traps() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (func $pass_er (export "pass_extern_ref") (param externref) (local.get 0) @@ -403,7 +406,7 @@ mod sys { #[test] fn extern_ref_ref_counting_table_instructions() -> Result<()> { - let store = Store::default(); + let mut store = Store::default(); let wat = r#"(module (table $table1 (export "table1") 2 12 externref) (table $table2 (export "table2") 6 12 externref) diff --git a/lib/c-api/examples/deprecated-header.c b/lib/c-api/examples/deprecated-header.c index 8e28bd78ef0..ee425c7cc12 100644 --- a/lib/c-api/examples/deprecated-header.c +++ b/lib/c-api/examples/deprecated-header.c @@ -21,8 +21,6 @@ int main(int argc, const char *argv[]) { printf("Initializing...\n"); own wasm_engine_t* engine = wasm_engine_new(); own wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // ===================== wasm_limits_t limits1 = { diff --git a/lib/c-api/examples/early-exit.c b/lib/c-api/examples/early-exit.c index 5bff06f343b..d2410ca8baf 100644 --- a/lib/c-api/examples/early-exit.c +++ b/lib/c-api/examples/early-exit.c @@ -29,7 +29,7 @@ void print_frame(wasm_frame_t* frame) { wasm_store_t *store = NULL; -own wasm_trap_t* early_exit(wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results) { +own wasm_trap_t* early_exit(const wasm_val_vec_t* args, wasm_val_vec_t* results) { own wasm_message_t trap_message; wasm_name_new_from_string_nt(&trap_message, "trapping from a host import"); own wasm_trap_t *trap = wasm_trap_new(store, &trap_message); @@ -42,8 +42,6 @@ int main(int argc, const char *argv[]) { printf("Initializing...\n"); wasm_engine_t *engine = wasm_engine_new(); store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/examples/exports-function.c b/lib/c-api/examples/exports-function.c index e7feaf4cd8f..8c644638870 100644 --- a/lib/c-api/examples/exports-function.c +++ b/lib/c-api/examples/exports-function.c @@ -20,8 +20,6 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/exports-global.c b/lib/c-api/examples/exports-global.c index dbbac9e81d6..ff20dfdeff4 100644 --- a/lib/c-api/examples/exports-global.c +++ b/lib/c-api/examples/exports-global.c @@ -19,8 +19,6 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/features.c b/lib/c-api/examples/features.c index 6f472617267..c42215d1eb1 100644 --- a/lib/c-api/examples/features.c +++ b/lib/c-api/examples/features.c @@ -26,8 +26,6 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new_with_config(config); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/imports-exports.c b/lib/c-api/examples/imports-exports.c index dca1efa57f8..e56a7232735 100644 --- a/lib/c-api/examples/imports-exports.c +++ b/lib/c-api/examples/imports-exports.c @@ -1,7 +1,7 @@ #include #include "wasmer.h" -wasm_trap_t* host_func_callback(wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results) { +wasm_trap_t* host_func_callback(const wasm_val_vec_t* args, wasm_val_vec_t* results) { printf("Calling back...\n> "); wasm_val_t val = WASM_I32_VAL(42); @@ -31,8 +31,6 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/instance.c b/lib/c-api/examples/instance.c index 2c50efee73e..6eb867d4ce0 100644 --- a/lib/c-api/examples/instance.c +++ b/lib/c-api/examples/instance.c @@ -20,8 +20,6 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/memory.c b/lib/c-api/examples/memory.c index cf6343ac6f5..d33295147b6 100644 --- a/lib/c-api/examples/memory.c +++ b/lib/c-api/examples/memory.c @@ -28,8 +28,6 @@ int main(int argc, const char* argv[]) { printf("Creating the store...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); printf("Compiling module...\n"); wasm_module_t* module = wasm_module_new(store, &wasm_bytes); diff --git a/lib/c-api/examples/memory2.c b/lib/c-api/examples/memory2.c index c9c0af980d7..8c009bd1f94 100644 --- a/lib/c-api/examples/memory2.c +++ b/lib/c-api/examples/memory2.c @@ -20,8 +20,6 @@ int main(int argc, const char *argv[]) { printf("Initializing...\n"); own wasm_engine_t* engine = wasm_engine_new(); own wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // ===================== wasm_limits_t limits1 = { diff --git a/lib/c-api/examples/wasi.c b/lib/c-api/examples/wasi.c index 932e605f888..529268e8591 100644 --- a/lib/c-api/examples/wasi.c +++ b/lib/c-api/examples/wasi.c @@ -36,16 +36,6 @@ int main(int argc, const char* argv[]) { wasi_config_arg(config, js_string); wasi_config_capture_stdout(config); - wasi_env_t* wasi_env = wasi_env_new(config); - if (!wasi_env) { - printf("> Error building WASI env!\n"); - print_wasmer_error(); - return 1; - } - - wasm_context_t* ctx = wasm_context_new(store, wasi_env); - wasm_store_context_set(store, ctx); - // Load binary. printf("Loading binary...\n"); FILE* file = fopen("assets/qjs.wasm", "r"); @@ -73,10 +63,27 @@ int main(int argc, const char* argv[]) { } wasm_byte_vec_delete(&binary); + + printf("Setting up WASI...\n"); + config = wasi_config_new("example_program"); + // TODO: error checking + js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));"; + wasi_config_arg(config, "--eval"); + wasi_config_arg(config, js_string); + wasi_config_capture_stdout(config); + + wasi_env_t* wasi_env = wasi_env_new(store, config); + + if (!wasi_env) { + printf("> Error building WASI env!\n"); + print_wasmer_error(); + return 1; + } + // Instantiate. printf("Instantiating module...\n"); wasm_extern_vec_t imports; - bool get_imports_result = wasi_get_imports(store, module, &imports); + bool get_imports_result = wasi_get_imports(store, wasi_env,module,&imports); if (!get_imports_result) { printf("> Error getting WASI imports!\n"); @@ -93,6 +100,12 @@ int main(int argc, const char* argv[]) { return 1; } + if (!wasi_env_initialize_instance(wasi_env, store, instance)) { + printf("> Error initializing wasi env memory!\n"); + print_wasmer_error(); + return 1; + } + // Extract export. printf("Extracting export...\n"); @@ -111,9 +124,6 @@ int main(int argc, const char* argv[]) { return 1; } - wasm_module_delete(module); - wasm_instance_delete(instance); - // Call. printf("Calling export...\n"); printf("Evaluating \"%s\"\n", js_string); @@ -170,6 +180,8 @@ int main(int argc, const char* argv[]) { printf("Shutting down...\n"); wasm_func_delete(run_func); wasi_env_delete(wasi_env); + wasm_module_delete(module); + wasm_instance_delete(instance); wasm_store_delete(store); wasm_engine_delete(engine); diff --git a/lib/c-api/src/wasm_c_api/context.rs b/lib/c-api/src/wasm_c_api/context.rs deleted file mode 100644 index cefc75076de..00000000000 --- a/lib/c-api/src/wasm_c_api/context.rs +++ /dev/null @@ -1,73 +0,0 @@ -use crate::wasm_c_api::store::wasm_store_t; -use libc::c_void; -use wasmer_api::{Context, ContextMut}; - -/// Opaque type representing a WebAssembly context. -#[allow(non_camel_case_types)] -pub struct wasm_context_t { - pub(crate) inner: Context<*mut c_void>, -} - -impl core::fmt::Debug for wasm_context_t { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "wasm_context_t") - } -} - -/// Creates a new WebAssembly Context given a specific [engine][super::engine]. -/// -/// # Example -/// -/// See the module's documentation. -#[no_mangle] -pub unsafe extern "C" fn wasm_context_new( - store: Option<&wasm_store_t>, - data: *mut c_void, -) -> Option> { - let store = store?; - - Some(Box::new(wasm_context_t { - inner: Context::new(&store.inner, data), - })) -} - -/// Deletes a WebAssembly context. -/// -/// # Example -/// -/// See the module's documentation. -#[no_mangle] -pub unsafe extern "C" fn wasm_context_delete(_context: Option>) {} - -/// Opaque type representing a mut ref of a WebAssembly context. -#[allow(non_camel_case_types)] -pub struct wasm_context_ref_mut_t<'a> { - pub(crate) inner: ContextMut<'a, *mut c_void>, -} - -/// Get the value of `wasm_context_ref_mut_t` data. -#[no_mangle] -pub unsafe extern "C" fn wasm_context_ref_mut_get(ctx: &wasm_context_ref_mut_t) -> *mut c_void { - *ctx.inner.data() -} - -/// Set the value of [`ContextMut`] data. -/// -#[no_mangle] -pub unsafe extern "C" fn wasm_context_ref_mut_set( - ctx: &mut wasm_context_ref_mut_t, - new_val: *mut c_void, -) { - *ctx.inner.data_mut() = new_val; -} - -/// Deletes a WebAssembly context. -/// -/// # Example -/// -/// See the module's documentation. -#[no_mangle] -pub unsafe extern "C" fn wasm_context_ref_mut_delete( - _context: Option<&mut wasm_context_ref_mut_t>, -) { -} diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index ca580bad17f..7ed8fa1df11 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -1,59 +1,61 @@ -use super::super::context::{wasm_context_ref_mut_t, wasm_context_t}; use super::super::store::wasm_store_t; use super::super::trap::wasm_trap_t; use super::super::types::{wasm_functype_t, wasm_valkind_enum}; use super::super::value::{wasm_val_inner, wasm_val_t, wasm_val_vec_t}; -use super::CApiExternTag; -use std::cell::RefCell; +use super::wasm_extern_t; +use crate::wasm_c_api::function_env::FunctionCEnv; +use libc::c_void; use std::convert::TryInto; -use std::ffi::c_void; use std::mem::MaybeUninit; -use std::rc::Rc; -use wasmer_api::{Function, RuntimeError, Value}; +use std::sync::{Arc, Mutex}; +use wasmer_api::{Extern, Function, FunctionEnv, FunctionEnvMut, RuntimeError, Value}; -#[derive(Debug, Clone)] +#[derive(Clone)] #[allow(non_camel_case_types)] #[repr(C)] pub struct wasm_func_t { - pub(crate) tag: CApiExternTag, - pub(crate) inner: Box, - pub(crate) context: Option>>, + pub(crate) extern_: wasm_extern_t, } impl wasm_func_t { - pub(crate) fn new(function: Function) -> Self { - Self { - tag: CApiExternTag::Function, - inner: Box::new(function), - context: None, + pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_func_t> { + match &e.inner { + Extern::Function(_) => Some(unsafe { &*(e as *const _ as *const _) }), + _ => None, } } } #[allow(non_camel_case_types)] pub type wasm_func_callback_t = unsafe extern "C" fn( - context: &mut wasm_context_ref_mut_t, args: &wasm_val_vec_t, results: &mut wasm_val_vec_t, ) -> Option>; +#[allow(non_camel_case_types)] +pub type wasm_func_callback_with_env_t = unsafe extern "C" fn( + env: *mut c_void, + args: &wasm_val_vec_t, + results: &mut wasm_val_vec_t, +) -> Option>; + +#[allow(non_camel_case_types)] +pub type wasm_env_finalizer_t = unsafe extern "C" fn(*mut c_void); + #[no_mangle] pub unsafe extern "C" fn wasm_func_new( - store: Option<&wasm_store_t>, + store: Option<&mut wasm_store_t>, function_type: Option<&wasm_functype_t>, callback: Option, ) -> Option> { let function_type = function_type?; let callback = callback?; let store = store?; - if store.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let mut ctx = store.context.as_ref()?.borrow_mut(); + let mut store_mut = store.inner.store_mut(); let func_sig = &function_type.inner().function_type; let num_rets = func_sig.results().len(); - let inner_callback = move |ctx: wasmer_api::ContextMut<'_, *mut c_void>, + let inner_callback = move |mut _ctx: FunctionEnvMut<'_, FunctionCEnv>, args: &[Value]| -> Result, RuntimeError> { let processed_args: wasm_val_vec_t = args @@ -72,11 +74,7 @@ pub unsafe extern "C" fn wasm_func_new( ] .into(); - let trap = callback( - &mut wasm_context_ref_mut_t { inner: ctx }, - &processed_args, - &mut results, - ); + let trap = callback(&processed_args, &mut results); if let Some(trap) = trap { return Err(trap.inner); @@ -91,12 +89,100 @@ pub unsafe extern "C" fn wasm_func_new( Ok(processed_results) }; - let function = Function::new(&mut ctx.inner, func_sig, inner_callback); - drop(ctx); - let mut retval = Box::new(wasm_func_t::new(function)); - retval.context = store.context.clone(); + let env = FunctionEnv::new(&mut store_mut, FunctionCEnv::default()); + let function = Function::new(&mut store_mut, &env, func_sig, inner_callback); + Some(Box::new(wasm_func_t { + extern_: wasm_extern_t::new(store.inner.clone(), function.into()), + })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_func_new_with_env( + store: Option<&mut wasm_store_t>, + function_type: Option<&wasm_functype_t>, + callback: Option, + env: *mut c_void, + env_finalizer: Option, +) -> Option> { + let function_type = function_type?; + let callback = callback?; + let store = store?; + let mut store_mut = store.inner.store_mut(); - Some(retval) + let func_sig = &function_type.inner().function_type; + let num_rets = func_sig.results().len(); + + #[derive(Clone)] + #[repr(C)] + struct WrapperEnv { + env: FunctionCEnv, + env_finalizer: Arc>>, + } + + // Only relevant when using multiple threads in the C API; + // Synchronization will be done via the C API / on the C side. + unsafe impl Send for WrapperEnv {} + unsafe impl Sync for WrapperEnv {} + + impl Drop for WrapperEnv { + fn drop(&mut self) { + if let Ok(mut guard) = self.env_finalizer.lock() { + if Arc::strong_count(&self.env_finalizer) == 1 { + if let Some(env_finalizer) = guard.take() { + unsafe { (env_finalizer)(self.env.as_ptr()) }; + } + } + } + } + } + let inner_callback = move |env: FunctionEnvMut<'_, WrapperEnv>, + args: &[Value]| + -> Result, RuntimeError> { + let processed_args: wasm_val_vec_t = args + .iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Argument conversion failed") + .into(); + + let mut results: wasm_val_vec_t = vec![ + wasm_val_t { + kind: wasm_valkind_enum::WASM_I64 as _, + of: wasm_val_inner { int64_t: 0 }, + }; + num_rets + ] + .into(); + + let trap = callback(env.data().env.as_ptr(), &processed_args, &mut results); + + if let Some(trap) = trap { + return Err(trap.inner); + } + + let processed_results = results + .take() + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .expect("Result conversion failed"); + + Ok(processed_results) + }; + let env = FunctionEnv::new( + &mut store_mut, + WrapperEnv { + env: FunctionCEnv::new(c_try!( + std::ptr::NonNull::new(env), + "Function environment cannot be a null pointer." + )), + env_finalizer: Arc::new(Mutex::new(env_finalizer)), + }, + ); + let function = Function::new(&mut store_mut, &env, func_sig, inner_callback); + Some(Box::new(wasm_func_t { + extern_: wasm_extern_t::new(store.inner.clone(), function.into()), + })) } #[no_mangle] @@ -109,17 +195,14 @@ pub unsafe extern "C" fn wasm_func_delete(_func: Option>) {} #[no_mangle] pub unsafe extern "C" fn wasm_func_call( - func: Option<&wasm_func_t>, + func: Option<&mut wasm_func_t>, args: Option<&wasm_val_vec_t>, results: &mut wasm_val_vec_t, ) -> Option> { let func = func?; let args = args?; - if func.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let mut ctx = func.context.as_ref()?.borrow_mut(); - + let mut store = func.extern_.store.clone(); + let mut store_mut = store.store_mut(); let params = args .as_slice() .iter() @@ -128,7 +211,7 @@ pub unsafe extern "C" fn wasm_func_call( .collect::, _>>() .expect("Arguments conversion failed"); - match func.inner.call(&mut ctx.inner, ¶ms) { + match func.extern_.function().call(&mut store_mut, ¶ms) { Ok(wasm_results) => { for (slot, val) in results .as_uninit_slice() @@ -146,31 +229,28 @@ pub unsafe extern "C" fn wasm_func_call( #[no_mangle] pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize { - let ctx = func - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - func.inner.ty(&ctx.inner).params().len() + func.extern_ + .function() + .ty(&func.extern_.store.store()) + .params() + .len() } #[no_mangle] pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize { - let ctx = func - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - func.inner.ty(&ctx.inner).results().len() + func.extern_ + .function() + .ty(&func.extern_.store.store()) + .results() + .len() } #[no_mangle] -pub extern "C" fn wasm_func_type(func: Option<&wasm_func_t>) -> Option> { +pub unsafe extern "C" fn wasm_func_type( + func: Option<&wasm_func_t>, +) -> Option> { let func = func?; - if func.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let ctx = func.context.as_ref()?.borrow(); - - Some(Box::new(wasm_functype_t::new(func.inner.ty(&ctx.inner)))) + Some(Box::new(wasm_functype_t::new( + func.extern_.function().ty(&func.extern_.store.store()), + ))) } diff --git a/lib/c-api/src/wasm_c_api/externals/global.rs b/lib/c-api/src/wasm_c_api/externals/global.rs index 3bd251b1430..b6f8a4f74f5 100644 --- a/lib/c-api/src/wasm_c_api/externals/global.rs +++ b/lib/c-api/src/wasm_c_api/externals/global.rs @@ -1,58 +1,47 @@ -use super::super::context::wasm_context_t; use super::super::store::wasm_store_t; use super::super::types::wasm_globaltype_t; use super::super::value::wasm_val_t; -use super::CApiExternTag; -use crate::error::update_last_error; -use std::cell::RefCell; +use super::wasm_extern_t; use std::convert::TryInto; -use std::rc::Rc; -use wasmer_api::{Global, Value}; +use wasmer_api::{Extern, Global, Value}; #[allow(non_camel_case_types)] #[repr(C)] -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct wasm_global_t { - pub(crate) tag: CApiExternTag, - pub(crate) inner: Box, - pub(crate) context: Option>>, + pub(crate) extern_: wasm_extern_t, } impl wasm_global_t { - pub(crate) fn new(global: Global) -> Self { - Self { - tag: CApiExternTag::Global, - inner: Box::new(global), - context: None, + pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_global_t> { + match &e.inner { + Extern::Global(_) => Some(unsafe { &*(e as *const _ as *const _) }), + _ => None, } } } #[no_mangle] pub unsafe extern "C" fn wasm_global_new( - store: Option<&wasm_store_t>, + store: Option<&mut wasm_store_t>, global_type: Option<&wasm_globaltype_t>, val: Option<&wasm_val_t>, ) -> Option> { let global_type = global_type?; let store = store?; - if store.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let mut ctx = store.context.as_ref()?.borrow_mut(); + let mut store_mut = store.inner.store_mut(); let val = val?; let global_type = &global_type.inner().global_type; let wasm_val = val.try_into().ok()?; let global = if global_type.mutability.is_mutable() { - Global::new_mut(&mut ctx.inner, wasm_val) + Global::new_mut(&mut store_mut, wasm_val) } else { - Global::new(&mut ctx.inner, wasm_val) + Global::new(&mut store_mut, wasm_val) }; - let mut retval = Box::new(wasm_global_t::new(global)); - retval.context = store.context.clone(); - - Some(retval) + Some(Box::new(wasm_global_t { + extern_: wasm_extern_t::new(store.inner.clone(), global.into()), + })) } #[no_mangle] @@ -61,42 +50,31 @@ pub unsafe extern "C" fn wasm_global_delete(_global: Option>) #[no_mangle] pub unsafe extern "C" fn wasm_global_copy(global: &wasm_global_t) -> Box { // do shallow copy - Box::new(wasm_global_t::new((&*global.inner).clone())) + Box::new(global.clone()) } #[no_mangle] pub unsafe extern "C" fn wasm_global_get( - global: &wasm_global_t, + global: &mut wasm_global_t, // own out: &mut wasm_val_t, ) { - match global.context.as_ref() { - Some(ctx) => { - let value = global.inner.get(&mut ctx.borrow_mut().inner); - *out = value.try_into().unwrap(); - } - None => { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - } + let value = global + .extern_ + .global() + .get(&mut global.extern_.store.store_mut()); + *out = value.try_into().unwrap(); } /// Note: This function returns nothing by design but it can raise an /// error if setting a new value fails. #[no_mangle] pub unsafe extern "C" fn wasm_global_set(global: &mut wasm_global_t, val: &wasm_val_t) { - match global.context.as_ref() { - Some(ctx) => { - let value: Value = val.try_into().unwrap(); - - if let Err(e) = global.inner.set(&mut ctx.borrow_mut().inner, value) { - update_last_error(e); - } - } - None => { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - } + let value: Value = val.try_into().unwrap(); + c_try!(global + .extern_ + .global() + .set(&mut global.extern_.store.store_mut(), value); otherwise ()); } #[no_mangle] @@ -104,20 +82,16 @@ pub unsafe extern "C" fn wasm_global_same( wasm_global1: &wasm_global_t, wasm_global2: &wasm_global_t, ) -> bool { - wasm_global1.inner == wasm_global2.inner + wasm_global1.extern_.global() == wasm_global2.extern_.global() } #[no_mangle] -pub extern "C" fn wasm_global_type( +pub unsafe extern "C" fn wasm_global_type( global: Option<&wasm_global_t>, ) -> Option> { let global = global?; - if global.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let ctx = global.context.as_ref()?.borrow(); Some(Box::new(wasm_globaltype_t::new( - global.inner.ty(&ctx.inner), + global.extern_.global().ty(&global.extern_.store.store()), ))) } @@ -133,8 +107,6 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); wasm_val_t forty_two = WASM_F32_VAL(42); wasm_val_t forty_three = WASM_F32_VAL(43); @@ -167,8 +139,6 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (global $global (export \"global\") f32 (f32.const 1)))"); diff --git a/lib/c-api/src/wasm_c_api/externals/memory.rs b/lib/c-api/src/wasm_c_api/externals/memory.rs index 6252b438751..1b1bee25529 100644 --- a/lib/c-api/src/wasm_c_api/externals/memory.rs +++ b/lib/c-api/src/wasm_c_api/externals/memory.rs @@ -1,47 +1,36 @@ -use super::super::context::wasm_context_t; -use super::super::store::wasm_store_t; use super::super::types::wasm_memorytype_t; -use super::CApiExternTag; -use std::cell::RefCell; -use std::rc::Rc; -use wasmer_api::{Memory, Pages}; +use super::{super::store::wasm_store_t, wasm_extern_t}; +use wasmer_api::{Extern, Memory, Pages}; #[allow(non_camel_case_types)] #[repr(C)] -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct wasm_memory_t { - pub(crate) tag: CApiExternTag, - pub(crate) inner: Box, - pub(crate) context: Option>>, + pub(crate) extern_: wasm_extern_t, } impl wasm_memory_t { - pub(crate) fn new(memory: Memory) -> Self { - Self { - tag: CApiExternTag::Memory, - inner: Box::new(memory), - context: None, + pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_memory_t> { + match &e.inner { + Extern::Memory(_) => Some(unsafe { &*(e as *const _ as *const _) }), + _ => None, } } } #[no_mangle] pub unsafe extern "C" fn wasm_memory_new( - store: Option<&wasm_store_t>, + store: Option<&mut wasm_store_t>, memory_type: Option<&wasm_memorytype_t>, ) -> Option> { let memory_type = memory_type?; let store = store?; - if store.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let mut ctx = store.context.as_ref()?.borrow_mut(); - + let mut store_mut = store.inner.store_mut(); let memory_type = memory_type.inner().memory_type; - let memory = c_try!(Memory::new(&mut ctx.inner, memory_type)); - let mut retval = Box::new(wasm_memory_t::new(memory)); - retval.context = store.context.clone(); - Some(retval) + let memory = c_try!(Memory::new(&mut store_mut, memory_type)); + Some(Box::new(wasm_memory_t { + extern_: wasm_extern_t::new(store.inner.clone(), memory.into()), + })) } #[no_mangle] @@ -50,7 +39,7 @@ pub unsafe extern "C" fn wasm_memory_delete(_memory: Option>) #[no_mangle] pub unsafe extern "C" fn wasm_memory_copy(memory: &wasm_memory_t) -> Box { // do shallow copy - Box::new(wasm_memory_t::new((&*memory.inner).clone())) + Box::new(memory.clone()) } #[no_mangle] @@ -58,7 +47,7 @@ pub unsafe extern "C" fn wasm_memory_same( wasm_memory1: &wasm_memory_t, wasm_memory2: &wasm_memory_t, ) -> bool { - wasm_memory1.inner == wasm_memory2.inner + wasm_memory1.extern_.memory() == wasm_memory2.extern_.memory() } #[no_mangle] @@ -66,56 +55,47 @@ pub unsafe extern "C" fn wasm_memory_type( memory: Option<&wasm_memory_t>, ) -> Option> { let memory = memory?; - if memory.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let ctx = memory.context.as_ref()?.borrow(); - Some(Box::new(wasm_memorytype_t::new( - memory.inner.ty(&ctx.inner), + memory.extern_.memory().ty(&memory.extern_.store.store()), ))) } // get a raw pointer into bytes #[no_mangle] pub unsafe extern "C" fn wasm_memory_data(memory: &mut wasm_memory_t) -> *mut u8 { - let ctx = memory - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - memory.inner.data_ptr(&ctx.inner) + memory + .extern_ + .memory() + .data_ptr(&memory.extern_.store.store()) } // size in bytes #[no_mangle] pub unsafe extern "C" fn wasm_memory_data_size(memory: &wasm_memory_t) -> usize { - let ctx = memory - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - memory.inner.size(&ctx.inner).bytes().0 + memory + .extern_ + .memory() + .size(&memory.extern_.store.store()) + .bytes() + .0 } // size in pages #[no_mangle] pub unsafe extern "C" fn wasm_memory_size(memory: &wasm_memory_t) -> u32 { - let ctx = memory - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - memory.inner.size(&ctx.inner).0 as _ + memory + .extern_ + .memory() + .size(&memory.extern_.store.store()) + .0 as _ } // delta is in pages #[no_mangle] pub unsafe extern "C" fn wasm_memory_grow(memory: &mut wasm_memory_t, delta: u32) -> bool { - let mut ctx = memory - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow_mut(); - memory.inner.grow(&mut ctx.inner, Pages(delta)).is_ok() + memory + .extern_ + .memory() + .grow(&mut memory.extern_.store.store_mut(), Pages(delta)) + .is_ok() } diff --git a/lib/c-api/src/wasm_c_api/externals/mod.rs b/lib/c-api/src/wasm_c_api/externals/mod.rs index 09d190c997f..9fe5eca1d4a 100644 --- a/lib/c-api/src/wasm_c_api/externals/mod.rs +++ b/lib/c-api/src/wasm_c_api/externals/mod.rs @@ -3,231 +3,77 @@ mod global; mod memory; mod table; -use super::context::wasm_context_t; -use super::store::wasm_store_t; +use super::store::StoreRef; +// use super::types::{wasm_externkind_enum, wasm_externkind_t}; pub use function::*; pub use global::*; pub use memory::*; -use std::cell::RefCell; -use std::mem::{self, ManuallyDrop}; -use std::rc::Rc; pub use table::*; -use wasmer_api::{Extern, ExternType}; +use wasmer_api::{Extern, ExternType, Function, Global, Memory, Table}; #[allow(non_camel_case_types)] -#[repr(transparent)] +#[derive(Clone)] pub struct wasm_extern_t { - pub(crate) inner: wasm_extern_inner, + pub(crate) inner: Extern, + pub(crate) store: StoreRef, } -/// All elements in this union must be `repr(C)` and have a -/// `CApiExternTag` as their first element. -#[allow(non_camel_case_types)] -pub(crate) union wasm_extern_inner { - function: mem::ManuallyDrop, - memory: mem::ManuallyDrop, - global: mem::ManuallyDrop, - table: mem::ManuallyDrop, -} - -#[cfg(test)] -mod extern_tests { - use super::*; - - #[test] - fn externs_are_the_same_size() { - use std::mem::{align_of, size_of}; - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::(), size_of::()); - - assert_eq!(align_of::(), align_of::()); - assert_eq!(align_of::(), align_of::()); - assert_eq!(align_of::(), align_of::()); - assert_eq!(align_of::(), align_of::()); - } - - #[test] - fn tags_are_the_same_offset_away() { - use field_offset::offset_of; - - let func_tag_offset = offset_of!(wasm_func_t => tag).get_byte_offset(); - let memory_tag_offset = offset_of!(wasm_memory_t => tag).get_byte_offset(); - let global_tag_offset = offset_of!(wasm_global_t => tag).get_byte_offset(); - let table_tag_offset = offset_of!(wasm_table_t => tag).get_byte_offset(); - - assert_eq!(func_tag_offset, memory_tag_offset); - assert_eq!(global_tag_offset, table_tag_offset); - assert_eq!(func_tag_offset, global_tag_offset); +impl wasm_extern_t { + pub(crate) fn new(store: StoreRef, inner: Extern) -> Self { + Self { inner, store } } -} -impl Drop for wasm_extern_inner { - fn drop(&mut self) { - unsafe { - match self.function.tag { - CApiExternTag::Function => mem::ManuallyDrop::drop(&mut self.function), - CApiExternTag::Global => mem::ManuallyDrop::drop(&mut self.global), - CApiExternTag::Table => mem::ManuallyDrop::drop(&mut self.table), - CApiExternTag::Memory => mem::ManuallyDrop::drop(&mut self.memory), - } + pub(crate) fn global(&self) -> Global { + match &self.inner { + Extern::Global(g) => g.clone(), + _ => unsafe { std::hint::unreachable_unchecked() }, } } -} - -impl wasm_extern_t { - pub(crate) fn get_tag(&self) -> CApiExternTag { - unsafe { self.inner.function.tag } - } - pub(crate) fn ty(&self) -> ExternType { - match self.get_tag() { - CApiExternTag::Function => unsafe { - let ctx = self - .inner - .function - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - ExternType::Function(self.inner.function.inner.ty(&ctx.inner)) - }, - CApiExternTag::Memory => unsafe { - let ctx = self - .inner - .memory - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - ExternType::Memory(self.inner.memory.inner.ty(&ctx.inner)) - }, - CApiExternTag::Global => unsafe { - let ctx = self - .inner - .global - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - ExternType::Global(self.inner.global.inner.ty(&ctx.inner)) - }, - CApiExternTag::Table => unsafe { - let ctx = self - .inner - .table - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - ExternType::Table(self.inner.table.inner.ty(&ctx.inner)) - }, + pub(crate) fn function(&self) -> Function { + match &self.inner { + Extern::Function(f) => f.clone(), + _ => unsafe { std::hint::unreachable_unchecked() }, } } - pub(crate) fn set_context(&mut self, new_val: Option>>) { - match self.get_tag() { - CApiExternTag::Function => unsafe { - (*self.inner.function).context = new_val; - }, - CApiExternTag::Memory => unsafe { - (*self.inner.memory).context = new_val; - }, - CApiExternTag::Global => unsafe { - (*self.inner.global).context = new_val; - }, - CApiExternTag::Table => unsafe { - (*self.inner.table).context = new_val; - }, + pub(crate) fn table(&self) -> Table { + match &self.inner { + Extern::Table(t) => t.clone(), + _ => unsafe { std::hint::unreachable_unchecked() }, } } -} -impl Clone for wasm_extern_t { - fn clone(&self) -> Self { - match self.get_tag() { - CApiExternTag::Function => Self { - inner: wasm_extern_inner { - function: unsafe { self.inner.function.clone() }, - }, - }, - CApiExternTag::Memory => Self { - inner: wasm_extern_inner { - memory: unsafe { self.inner.memory.clone() }, - }, - }, - CApiExternTag::Global => Self { - inner: wasm_extern_inner { - global: unsafe { self.inner.global.clone() }, - }, - }, - CApiExternTag::Table => Self { - inner: wasm_extern_inner { - table: unsafe { self.inner.table.clone() }, - }, - }, + pub(crate) fn memory(&self) -> Memory { + match &self.inner { + Extern::Memory(m) => m.clone(), + _ => unsafe { std::hint::unreachable_unchecked() }, } } } -impl From for wasm_extern_t { - fn from(other: Extern) -> Self { - match other { - Extern::Function(function) => Self { - inner: wasm_extern_inner { - function: mem::ManuallyDrop::new(wasm_func_t::new(function)), - }, - }, - Extern::Memory(memory) => Self { - inner: wasm_extern_inner { - memory: mem::ManuallyDrop::new(wasm_memory_t::new(memory)), - }, - }, - Extern::Table(table) => Self { - inner: wasm_extern_inner { - table: mem::ManuallyDrop::new(wasm_table_t::new(table)), - }, - }, - Extern::Global(global) => Self { - inner: wasm_extern_inner { - global: mem::ManuallyDrop::new(wasm_global_t::new(global)), - }, - }, - } +// #[no_mangle] +// pub extern "C" fn wasm_extern_kind(e: &wasm_extern_t) -> wasm_externkind_t { +// (match e.inner { +// Extern::Function(_) => wasm_externkind_enum::WASM_EXTERN_FUNC, +// Extern::Table(_) => wasm_externkind_enum::WASM_EXTERN_TABLE, +// Extern::Global(_) => wasm_externkind_enum::WASM_EXTERN_GLOBAL, +// Extern::Memory(_) => wasm_externkind_enum::WASM_EXTERN_MEMORY, +// }) as wasm_externkind_t +// } + +impl wasm_extern_t { + pub(crate) unsafe fn ty(&self) -> ExternType { + self.inner.ty(&self.store.store()) } } impl From for Extern { - fn from(mut other: wasm_extern_t) -> Self { - let out = match other.get_tag() { - CApiExternTag::Function => unsafe { - (*ManuallyDrop::take(&mut other.inner.function).inner).into() - }, - CApiExternTag::Memory => unsafe { - (*ManuallyDrop::take(&mut other.inner.memory).inner).into() - }, - CApiExternTag::Table => unsafe { - (*ManuallyDrop::take(&mut other.inner.table).inner).into() - }, - CApiExternTag::Global => unsafe { - (*ManuallyDrop::take(&mut other.inner.global).inner).into() - }, - }; - mem::forget(other); - out + fn from(other: wasm_extern_t) -> Self { + other.inner } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] -pub(crate) enum CApiExternTag { - Function, - Global, - Table, - Memory, -} - wasm_declare_boxed_vec!(extern); /// Copy a `wasm_extern_t`. @@ -242,70 +88,46 @@ pub unsafe extern "C" fn wasm_extern_delete(_extern: Option>) #[no_mangle] pub extern "C" fn wasm_func_as_extern(func: Option<&wasm_func_t>) -> Option<&wasm_extern_t> { - unsafe { mem::transmute::, Option<&wasm_extern_t>>(func) } + Some(&func?.extern_) } #[no_mangle] pub extern "C" fn wasm_global_as_extern(global: Option<&wasm_global_t>) -> Option<&wasm_extern_t> { - unsafe { mem::transmute::, Option<&wasm_extern_t>>(global) } + Some(&global?.extern_) } #[no_mangle] pub extern "C" fn wasm_memory_as_extern(memory: Option<&wasm_memory_t>) -> Option<&wasm_extern_t> { - unsafe { mem::transmute::, Option<&wasm_extern_t>>(memory) } + Some(&memory?.extern_) } #[no_mangle] pub extern "C" fn wasm_table_as_extern(table: Option<&wasm_table_t>) -> Option<&wasm_extern_t> { - unsafe { mem::transmute::, Option<&wasm_extern_t>>(table) } + Some(&table?.extern_) } #[no_mangle] pub extern "C" fn wasm_extern_as_func(r#extern: Option<&wasm_extern_t>) -> Option<&wasm_func_t> { - let r#extern = r#extern?; - - if r#extern.get_tag() == CApiExternTag::Function { - Some(unsafe { mem::transmute::<&wasm_extern_t, &wasm_func_t>(r#extern) }) - } else { - None - } + wasm_func_t::try_from(r#extern?) } #[no_mangle] pub extern "C" fn wasm_extern_as_global( r#extern: Option<&wasm_extern_t>, ) -> Option<&wasm_global_t> { - let r#extern = r#extern?; - - if r#extern.get_tag() == CApiExternTag::Global { - Some(unsafe { mem::transmute::<&wasm_extern_t, &wasm_global_t>(r#extern) }) - } else { - None - } + wasm_global_t::try_from(r#extern?) } #[no_mangle] pub extern "C" fn wasm_extern_as_memory( r#extern: Option<&wasm_extern_t>, ) -> Option<&wasm_memory_t> { - let r#extern = r#extern?; - - if r#extern.get_tag() == CApiExternTag::Memory { - Some(unsafe { mem::transmute::<&wasm_extern_t, &wasm_memory_t>(r#extern) }) - } else { - None - } + wasm_memory_t::try_from(r#extern?) } #[no_mangle] pub extern "C" fn wasm_extern_as_table(r#extern: Option<&wasm_extern_t>) -> Option<&wasm_table_t> { - let r#extern = r#extern?; - - if r#extern.get_tag() == CApiExternTag::Table { - Some(unsafe { mem::transmute::<&wasm_extern_t, &wasm_table_t>(r#extern) }) - } else { - None - } + wasm_table_t::try_from(r#extern?) } #[cfg(test)] @@ -320,8 +142,6 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string( diff --git a/lib/c-api/src/wasm_c_api/externals/table.rs b/lib/c-api/src/wasm_c_api/externals/table.rs index 300b91ee1c4..839cb447f14 100644 --- a/lib/c-api/src/wasm_c_api/externals/table.rs +++ b/lib/c-api/src/wasm_c_api/externals/table.rs @@ -1,26 +1,20 @@ -use super::super::context::wasm_context_t; use super::super::store::wasm_store_t; use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t}; -use super::CApiExternTag; -use std::cell::RefCell; -use std::rc::Rc; -use wasmer_api::Table; +use super::wasm_extern_t; +use wasmer_api::Extern; #[allow(non_camel_case_types)] #[repr(C)] #[derive(Clone)] pub struct wasm_table_t { - pub(crate) tag: CApiExternTag, - pub(crate) inner: Box
, - pub(crate) context: Option>>, + pub(crate) extern_: wasm_extern_t, } impl wasm_table_t { - pub(crate) fn new(table: Table) -> Self { - Self { - tag: CApiExternTag::Table, - inner: Box::new(table), - context: None, + pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_table_t> { + match &e.inner { + Extern::Table(_) => Some(unsafe { &*(e as *const _ as *const _) }), + _ => None, } } } @@ -40,17 +34,12 @@ pub unsafe extern "C" fn wasm_table_delete(_table: Option>) {} #[no_mangle] pub unsafe extern "C" fn wasm_table_copy(table: &wasm_table_t) -> Box { // do shallow copy - Box::new(wasm_table_t::new((&*table.inner).clone())) + Box::new(table.clone()) } #[no_mangle] pub unsafe extern "C" fn wasm_table_size(table: &wasm_table_t) -> usize { - let ctx = table - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow(); - table.inner.size(&ctx.inner) as _ + table.extern_.table().size(&table.extern_.store.store()) as _ } #[no_mangle] @@ -58,7 +47,7 @@ pub unsafe extern "C" fn wasm_table_same( wasm_table1: &wasm_table_t, wasm_table2: &wasm_table_t, ) -> bool { - wasm_table1.inner == wasm_table2.inner + wasm_table1.extern_.table() == wasm_table2.extern_.table() } #[no_mangle] diff --git a/lib/c-api/src/wasm_c_api/function_env.rs b/lib/c-api/src/wasm_c_api/function_env.rs new file mode 100644 index 00000000000..a9e3910ab07 --- /dev/null +++ b/lib/c-api/src/wasm_c_api/function_env.rs @@ -0,0 +1,63 @@ +use crate::wasm_c_api::store::wasm_store_t; +use std::ffi::c_void; +use wasmer_api::FunctionEnv; + +#[derive(Clone, Copy)] +#[repr(C)] +pub struct FunctionCEnv { + #[allow(dead_code)] + inner: std::ptr::NonNull, +} + +impl FunctionCEnv { + #[allow(dead_code)] + pub(crate) fn as_ptr(&self) -> *mut c_void { + self.inner.as_ptr() + } +} + +static NULL_ENV_PLACEHOLDER: u32 = 42; + +impl FunctionCEnv { + pub(crate) fn new(inner: std::ptr::NonNull) -> Self { + Self { inner } + } +} + +impl Default for FunctionCEnv { + fn default() -> Self { + Self { + inner: unsafe { + std::ptr::NonNull::new_unchecked( + &NULL_ENV_PLACEHOLDER as *const u32 as *mut u32 as *mut c_void, + ) + }, + } + } +} + +unsafe impl Send for FunctionCEnv {} + +#[derive(Clone)] +#[allow(non_camel_case_types)] +#[repr(C)] +pub struct wasmer_funcenv_t { + inner: FunctionCEnv, +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_funcenv_new( + store: Option<&mut wasm_store_t>, + mut data: *mut c_void, +) -> Option> { + let store = store?; + if data.is_null() { + data = &NULL_ENV_PLACEHOLDER as *const u32 as *mut u32 as *mut c_void; + } + let inner = FunctionCEnv::new(std::ptr::NonNull::new_unchecked(data)); + let _ = FunctionEnv::new(&mut store.inner.store_mut(), inner); + Some(Box::new(wasmer_funcenv_t { inner })) +} + +#[no_mangle] +pub unsafe extern "C" fn wasmer_funcenv_delete(_funcenv: Option>) {} diff --git a/lib/c-api/src/wasm_c_api/instance.rs b/lib/c-api/src/wasm_c_api/instance.rs index 9d363815b4d..c32b44fbe93 100644 --- a/lib/c-api/src/wasm_c_api/instance.rs +++ b/lib/c-api/src/wasm_c_api/instance.rs @@ -1,18 +1,14 @@ -use super::context::wasm_context_t; use super::externals::{wasm_extern_t, wasm_extern_vec_t}; use super::module::wasm_module_t; -use super::store::wasm_store_t; +use super::store::{wasm_store_t, StoreRef}; use super::trap::wasm_trap_t; -use std::cell::RefCell; -use std::rc::Rc; -use std::sync::Arc; use wasmer_api::{Extern, Instance, InstantiationError}; /// Opaque type representing a WebAssembly instance. #[allow(non_camel_case_types)] pub struct wasm_instance_t { - pub(crate) inner: Arc, - pub(crate) context: Option>>, + pub(crate) store: StoreRef, + pub(crate) inner: Instance, } /// Creates a new instance from a WebAssembly module and a @@ -40,16 +36,13 @@ pub struct wasm_instance_t { /// See the module's documentation. #[no_mangle] pub unsafe extern "C" fn wasm_instance_new( - store: Option<&wasm_store_t>, + store: Option<&mut wasm_store_t>, module: Option<&wasm_module_t>, imports: Option<&wasm_extern_vec_t>, trap: Option<&mut *mut wasm_trap_t>, ) -> Option> { let store = store?; - if store.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let mut ctx = store.context.as_ref()?.borrow_mut(); + let mut store_mut = store.inner.store_mut(); let module = module?; let imports = imports?; @@ -63,8 +56,8 @@ pub unsafe extern "C" fn wasm_instance_new( .take(module_import_count) .collect::>(); - let instance = match Instance::new_by_index(&mut ctx.inner, wasm_module, &externs) { - Ok(instance) => Arc::new(instance), + let instance = match Instance::new_by_index(&mut store_mut, wasm_module, &externs) { + Ok(instance) => instance, Err(InstantiationError::Link(link_error)) => { crate::error::update_last_error(link_error); @@ -87,7 +80,7 @@ pub unsafe extern "C" fn wasm_instance_new( return None; } - Err(e @ InstantiationError::BadContext) => { + Err(e @ InstantiationError::DifferentStores) => { crate::error::update_last_error(e); return None; @@ -95,8 +88,8 @@ pub unsafe extern "C" fn wasm_instance_new( }; Some(Box::new(wasm_instance_t { + store: store.inner.clone(), inner: instance, - context: store.context.clone(), })) } @@ -122,8 +115,6 @@ pub unsafe extern "C" fn wasm_instance_delete(_instance: Option>> = instance + let extern_vec: Vec>> = instance .exports .iter() - .map(|(_name, r#extern)| Some(Box::new(r#extern.clone().into()))) + .map(|(_name, r#extern)| { + Some(Box::new(wasm_extern_t::new( + original_instance.store.clone(), + r#extern.clone(), + ))) + }) .collect(); - for ex in extern_vec.iter_mut().flatten() { - ex.set_context(original_instance.context.clone()); - } - out.set_buffer(extern_vec); } @@ -224,11 +216,9 @@ mod tests { // The `sum` host function implementation. wasm_trap_t* sum_callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* arguments, wasm_val_vec_t* results ) { - (void) ctx_mut; wasm_val_t sum = { .kind = WASM_I32, .of = { arguments->data[0].of.i32 + arguments->data[1].of.i32 }, @@ -242,8 +232,6 @@ mod tests { // Create the engine and the store. wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Create a WebAssembly module from a WAT definition. wasm_byte_vec_t wat; diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 04aa90f3d60..c74187ddfda 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -297,6 +297,16 @@ macro_rules! wasm_impl_copy_delete { } macro_rules! c_try { + ($expr:expr; otherwise ()) => {{ + let res: Result<_, _> = $expr; + match res { + Ok(val) => val, + Err(err) => { + crate::error::update_last_error(err); + return; + } + } + }}; ($expr:expr; otherwise $return:expr) => {{ let res: Result<_, _> = $expr; match res { diff --git a/lib/c-api/src/wasm_c_api/mod.rs b/lib/c-api/src/wasm_c_api/mod.rs index 26fbd5f991b..5ec333e320a 100644 --- a/lib/c-api/src/wasm_c_api/mod.rs +++ b/lib/c-api/src/wasm_c_api/mod.rs @@ -22,7 +22,7 @@ //! discovery of this API. /// `Context`. -mod context; +mod function_env; /// Private Rust macros. #[macro_use] @@ -92,8 +92,6 @@ pub mod externals; /// // Create the engine and the store. /// wasm_engine_t* engine = wasm_engine_new(); /// wasm_store_t* store = wasm_store_new(engine); -/// wasm_context_t* ctx = wasm_context_new(store, 0); -/// wasm_store_context_set(store, ctx); /// /// // Create a WebAssembly module from a WAT definition. /// wasm_byte_vec_t wat; diff --git a/lib/c-api/src/wasm_c_api/module.rs b/lib/c-api/src/wasm_c_api/module.rs index 5eb0a716da0..26cbfd3fcb5 100644 --- a/lib/c-api/src/wasm_c_api/module.rs +++ b/lib/c-api/src/wasm_c_api/module.rs @@ -1,14 +1,13 @@ use super::store::wasm_store_t; use super::types::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t}; -use crate::error::update_last_error; use std::ptr::NonNull; -use std::sync::Arc; use wasmer_api::Module; /// Opaque type representing a WebAssembly module. +#[derive(Clone)] #[allow(non_camel_case_types)] pub struct wasm_module_t { - pub(crate) inner: Arc, + pub(crate) inner: Module, } /// A WebAssembly module contains stateless WebAssembly code that has @@ -27,17 +26,15 @@ pub struct wasm_module_t { /// See the module's documentation. #[no_mangle] pub unsafe extern "C" fn wasm_module_new( - store: Option<&wasm_store_t>, + store: Option<&mut wasm_store_t>, bytes: Option<&wasm_byte_vec_t>, ) -> Option> { - let store = store?; + let store = store?.inner.store_mut(); let bytes = bytes?; - let module = c_try!(Module::from_binary(&store.inner, bytes.as_slice())); + let module = c_try!(Module::from_binary(&store, bytes.as_slice())); - Some(Box::new(wasm_module_t { - inner: Arc::new(module), - })) + Some(Box::new(wasm_module_t { inner: module })) } /// Deletes a WebAssembly module. @@ -91,11 +88,11 @@ pub unsafe extern "C" fn wasm_module_delete(_module: Option>) /// ``` #[no_mangle] pub unsafe extern "C" fn wasm_module_validate( - store: Option<&wasm_store_t>, + store: Option<&mut wasm_store_t>, bytes: Option<&wasm_byte_vec_t>, ) -> bool { let store = match store { - Some(store) => store, + Some(store) => store.inner.store_mut(), None => return false, }; let bytes = match bytes { @@ -103,13 +100,9 @@ pub unsafe extern "C" fn wasm_module_validate( None => return false, }; - if let Err(error) = Module::validate(&store.inner, bytes.as_slice()) { - update_last_error(error); - - false - } else { - true - } + Module::validate(&store, bytes.as_slice()) + .map(|_| true) + .unwrap_or(false) } /// Returns an array of the exported types in the module. @@ -465,12 +458,10 @@ pub unsafe extern "C" fn wasm_module_deserialize( ) -> Option> { let bytes = bytes?; - let module = c_try!(Module::deserialize(&store.inner, bytes.as_slice())); + let module = c_try!(Module::deserialize(&store.inner.store(), bytes.as_slice())); Some(NonNull::new_unchecked(Box::into_raw(Box::new( - wasm_module_t { - inner: Arc::new(module), - }, + wasm_module_t { inner: module }, )))) } @@ -483,13 +474,7 @@ pub unsafe extern "C" fn wasm_module_deserialize( /// See [`wasm_module_deserialize`]. #[no_mangle] pub unsafe extern "C" fn wasm_module_serialize(module: &wasm_module_t, out: &mut wasm_byte_vec_t) { - let byte_vec = match module.inner.serialize() { - Ok(byte_vec) => byte_vec, - Err(err) => { - crate::error::update_last_error(err); - return; - } - }; + let byte_vec = c_try!(module.inner.serialize(); otherwise ()); out.set_buffer(byte_vec); } diff --git a/lib/c-api/src/wasm_c_api/store.rs b/lib/c-api/src/wasm_c_api/store.rs index fe5eb89de21..d6bd5415ef5 100644 --- a/lib/c-api/src/wasm_c_api/store.rs +++ b/lib/c-api/src/wasm_c_api/store.rs @@ -1,20 +1,27 @@ -use super::context::wasm_context_t; use super::engine::wasm_engine_t; -use libc::c_void; -use std::cell::RefCell; -use std::rc::Rc; -use wasmer_api::Store; +use std::cell::UnsafeCell; +use std::sync::Arc; +use wasmer_api::{AsStoreMut, AsStoreRef, Store, StoreMut, StoreRef as BaseStoreRef}; + +#[derive(Clone)] +pub struct StoreRef { + inner: Arc>, +} + +impl StoreRef { + pub unsafe fn store(&self) -> BaseStoreRef<'_> { + (*self.inner.get()).as_store_ref() + } + + pub unsafe fn store_mut(&mut self) -> StoreMut<'_> { + (*self.inner.get()).as_store_mut() + } +} /// Opaque type representing a WebAssembly store. #[allow(non_camel_case_types)] pub struct wasm_store_t { - pub(crate) inner: Store, - pub(crate) context: Option>>, -} - -impl wasm_store_t { - pub(crate) const CTX_ERR_STR: &'static str = - "store used without a Context set; use wasm_store_context_set() after initializing your store."; + pub(crate) inner: StoreRef, } /// Creates a new WebAssembly store given a specific [engine][super::engine]. @@ -30,63 +37,12 @@ pub unsafe extern "C" fn wasm_store_new( let store = Store::new_with_engine(&*engine.inner); Some(Box::new(wasm_store_t { - inner: store, - context: None, + inner: StoreRef { + inner: Arc::new(UnsafeCell::new(store)), + }, })) } -/// Sets the context for this WebAssembly store. -/// -/// # Example -/// -/// See the module's documentation. -#[no_mangle] -pub unsafe extern "C" fn wasm_store_context_set( - store: Option<&mut wasm_store_t>, - context: Option>, -) { - let _result = (move |store: Option<&mut wasm_store_t>, - context: Option>| - -> Option<()> { - let mut store = store?; - let context = context?; - store.context = Some(Rc::new(RefCell::new(*context))); - Some(()) - })(store, context); -} - -/// Get the value of Context data. -/// -/// # Example -/// -/// See the module's documentation. -#[no_mangle] -pub unsafe extern "C" fn wasm_store_data_get(store: &wasm_store_t) -> *mut c_void { - *store - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow() - .inner - .data() -} - -/// Set the value of Context data. -/// -/// # Example -/// -/// See the module's documentation. -#[no_mangle] -pub unsafe extern "C" fn wasm_store_data_set(store: &mut wasm_store_t, new_val: *mut c_void) { - *store - .context - .as_mut() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow_mut() - .inner - .data_mut() = new_val; -} - /// Deletes a WebAssembly store. /// /// # Example diff --git a/lib/c-api/src/wasm_c_api/types/extern_.rs b/lib/c-api/src/wasm_c_api/types/extern_.rs index b97f4f54f15..4218c2a70d4 100644 --- a/lib/c-api/src/wasm_c_api/types/extern_.rs +++ b/lib/c-api/src/wasm_c_api/types/extern_.rs @@ -9,7 +9,7 @@ use thiserror::Error; use wasmer_api::ExternType; #[allow(non_camel_case_types)] -type wasm_externkind_t = u8; +pub type wasm_externkind_t = u8; #[allow(non_camel_case_types)] #[repr(u8)] diff --git a/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs b/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs index bc4eb715470..f46301e672f 100644 --- a/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs +++ b/lib/c-api/src/wasm_c_api/unstable/middlewares/metering.rs @@ -45,8 +45,6 @@ //! // Create the engine and the store based on the configuration. //! wasm_engine_t* engine = wasm_engine_new_with_config(config); //! wasm_store_t* store = wasm_store_new(engine); -//! wasm_context_t* ctx = wasm_context_new(store, 0); -//! wasm_store_context_set(store, ctx); //! //! // Create the new WebAssembly module. //! wasm_byte_vec_t wat; @@ -134,7 +132,6 @@ //! ``` use super::super::super::instance::wasm_instance_t; -use super::super::super::store::wasm_store_t; use super::super::parser::operator::wasmer_parser_operator_t; use super::wasmer_middleware_t; use std::sync::Arc; @@ -204,13 +201,10 @@ pub extern "C" fn wasmer_metering_delete(_metering: Option u64 { - let mut ctx = instance - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow_mut(); - match get_remaining_points(&mut ctx.inner, &instance.inner) { +pub unsafe extern "C" fn wasmer_metering_get_remaining_points( + instance: &mut wasm_instance_t, +) -> u64 { + match get_remaining_points(&mut instance.store.store_mut(), &instance.inner) { MeteringPoints::Remaining(value) => value, MeteringPoints::Exhausted => std::u64::MAX, } @@ -222,14 +216,11 @@ pub extern "C" fn wasmer_metering_get_remaining_points(instance: &wasm_instance_ /// /// See module's documentation. #[no_mangle] -pub extern "C" fn wasmer_metering_points_are_exhausted(instance: &wasm_instance_t) -> bool { - let mut ctx = instance - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow_mut(); +pub unsafe extern "C" fn wasmer_metering_points_are_exhausted( + instance: &mut wasm_instance_t, +) -> bool { matches!( - get_remaining_points(&mut ctx.inner, &instance.inner), + get_remaining_points(&mut instance.store.store_mut(), &instance.inner), MeteringPoints::Exhausted, ) } @@ -271,8 +262,6 @@ pub extern "C" fn wasmer_metering_points_are_exhausted(instance: &wasm_instance_ /// wasm_engine_t* engine = wasm_engine_new_with_config(config); /// /// wasm_store_t* store = wasm_store_new(engine); -/// wasm_context_t* ctx = wasm_context_new(store, 0); -/// wasm_store_context_set(store, ctx); /// /// // Create the module and instantiate it. /// wasm_byte_vec_t wat; @@ -309,13 +298,11 @@ pub extern "C" fn wasmer_metering_points_are_exhausted(instance: &wasm_instance_ /// # } /// ``` #[no_mangle] -pub extern "C" fn wasmer_metering_set_remaining_points(instance: &wasm_instance_t, new_limit: u64) { - let mut ctx = instance - .context - .as_ref() - .expect(wasm_store_t::CTX_ERR_STR) - .borrow_mut(); - set_remaining_points(&mut ctx.inner, &instance.inner, new_limit); +pub unsafe extern "C" fn wasmer_metering_set_remaining_points( + instance: &mut wasm_instance_t, + new_limit: u64, +) { + set_remaining_points(&mut instance.store.store_mut(), &instance.inner, new_limit); } /// Transforms a [`wasmer_metering_t`] into a generic diff --git a/lib/c-api/src/wasm_c_api/unstable/module.rs b/lib/c-api/src/wasm_c_api/unstable/module.rs index 81528369bd0..b53e0b14608 100644 --- a/lib/c-api/src/wasm_c_api/unstable/module.rs +++ b/lib/c-api/src/wasm_c_api/unstable/module.rs @@ -4,7 +4,6 @@ use super::super::module::wasm_module_t; use super::super::types::wasm_name_t; use std::ptr; use std::str; -use std::sync::Arc; /// Unstable non-standard Wasmer-specific API to get the module's /// name, otherwise `out->size` is set to `0` and `out->data` to @@ -149,8 +148,5 @@ pub unsafe extern "C" fn wasmer_module_set_name( Err(_) => return false, // not ideal! }; - match Arc::get_mut(&mut module.inner) { - Some(module) => module.set_name(name), - None => false, - } + module.inner.set_name(name) } diff --git a/lib/c-api/src/wasm_c_api/unstable/wasi.rs b/lib/c-api/src/wasm_c_api/unstable/wasi.rs index 0abbf923267..f37a5e510f8 100644 --- a/lib/c-api/src/wasm_c_api/unstable/wasi.rs +++ b/lib/c-api/src/wasm_c_api/unstable/wasi.rs @@ -2,11 +2,8 @@ //! API. use super::super::{ - externals::wasm_extern_t, module::wasm_module_t, store::wasm_store_t, types::wasm_name_t, - wasi::wasi_env_t, + externals::wasm_extern_t, module::wasm_module_t, types::wasm_name_t, wasi::wasi_env_t, }; -use wasmer_api::{AsContextMut, Extern}; -use wasmer_wasi::{generate_import_object_from_ctx, get_wasi_version}; /// Unstable non-standard type wrapping `wasm_extern_t` with the /// addition of two `wasm_name_t` respectively for the module name and @@ -147,46 +144,36 @@ pub extern "C" fn wasmer_named_extern_unwrap( /// based on the `wasm_module_t` requirements. #[no_mangle] pub unsafe extern "C" fn wasi_get_unordered_imports( - store: Option<&wasm_store_t>, + wasi_env: Option<&mut wasi_env_t>, module: Option<&wasm_module_t>, - wasi_env: Option<&wasi_env_t>, imports: &mut wasmer_named_extern_vec_t, ) -> bool { - wasi_get_unordered_imports_inner(store, module, wasi_env, imports).is_some() + wasi_get_unordered_imports_inner(wasi_env, module, imports).is_some() } -fn wasi_get_unordered_imports_inner( - store: Option<&wasm_store_t>, +unsafe fn wasi_get_unordered_imports_inner( + wasi_env: Option<&mut wasi_env_t>, module: Option<&wasm_module_t>, - wasi_env: Option<&wasi_env_t>, imports: &mut wasmer_named_extern_vec_t, ) -> Option<()> { - let store = store?; - if store.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let mut ctx = store.context.as_ref()?.borrow_mut(); + let wasi_env = wasi_env?; + let store = &mut wasi_env.store; + let mut store_mut = store.store_mut(); let module = module?; - let _wasi_env = wasi_env?; - - let version = c_try!(get_wasi_version(&module.inner, false) - .ok_or("could not detect a WASI version on the given module")); - let inner = unsafe { ctx.inner.transmute_data::() }; - let import_object = generate_import_object_from_ctx(&mut inner.as_context_mut(), version); + let import_object = c_try!(wasi_env.inner.import_object(&mut store_mut, &module.inner)); imports.set_buffer( import_object .into_iter() - .map(|((module, name), extern_)| { + .map(move |((module, name), extern_)| { let module = module.into(); let name = name.into(); - let extern_inner = Extern::from_vm_extern(&mut ctx.inner, extern_.to_vm_extern()); Some(Box::new(wasmer_named_extern_t { module, name, - r#extern: Box::new(extern_inner.into()), + r#extern: Box::new(wasm_extern_t::new(store.clone(), extern_)), })) }) .collect::>(), diff --git a/lib/c-api/src/wasm_c_api/value.rs b/lib/c-api/src/wasm_c_api/value.rs index db07a813b4c..130bb9782dd 100644 --- a/lib/c-api/src/wasm_c_api/value.rs +++ b/lib/c-api/src/wasm_c_api/value.rs @@ -1,5 +1,4 @@ use super::types::{wasm_ref_t, wasm_valkind_enum}; -use crate::error::update_last_error; use std::convert::{TryFrom, TryInto}; use wasmer_api::Value; @@ -137,8 +136,8 @@ pub unsafe extern "C" fn wasm_val_copy( val: &wasm_val_t, ) { out.kind = val.kind; - out.of = match val.kind.try_into() { - Ok(kind) => match kind { + out.of = c_try!(val.kind.try_into().map(|kind| { + match kind { wasm_valkind_enum::WASM_I32 => wasm_val_inner { int32_t: val.of.int32_t, }, @@ -153,14 +152,8 @@ pub unsafe extern "C" fn wasm_val_copy( }, wasm_valkind_enum::WASM_ANYREF => wasm_val_inner { wref: val.of.wref }, wasm_valkind_enum::WASM_FUNCREF => wasm_val_inner { wref: val.of.wref }, - }, - - Err(e) => { - update_last_error(e); - - return; } - }; + }); otherwise ()); } #[no_mangle] diff --git a/lib/c-api/src/wasm_c_api/wasi/mod.rs b/lib/c-api/src/wasm_c_api/wasi/mod.rs index 1e7dc61a0b7..54ed50ed46b 100644 --- a/lib/c-api/src/wasm_c_api/wasi/mod.rs +++ b/lib/c-api/src/wasm_c_api/wasi/mod.rs @@ -4,20 +4,18 @@ pub use super::unstable::wasi::wasi_get_unordered_imports; use super::{ - externals::{wasm_extern_vec_t, wasm_func_t}, + externals::{wasm_extern_t, wasm_extern_vec_t, wasm_func_t}, instance::wasm_instance_t, module::wasm_module_t, - store::wasm_store_t, + store::{wasm_store_t, StoreRef}, }; use crate::error::update_last_error; use std::convert::TryFrom; use std::ffi::CStr; use std::os::raw::c_char; use std::slice; -use wasmer_api::{AsContextMut, Extern}; use wasmer_wasi::{ - generate_import_object_from_ctx, get_wasi_version, Pipe, WasiEnv, WasiFile, WasiState, - WasiStateBuilder, WasiVersion, + get_wasi_version, Pipe, WasiFile, WasiFunctionEnv, WasiState, WasiStateBuilder, WasiVersion, }; #[derive(Debug)] @@ -163,14 +161,20 @@ pub extern "C" fn wasi_config_inherit_stdin(config: &mut wasi_config_t) { #[allow(non_camel_case_types)] pub struct wasi_env_t { /// cbindgen:ignore - pub(super) inner: WasiEnv, + pub(super) inner: WasiFunctionEnv, + pub(super) store: StoreRef, } /// Create a new WASI environment. /// /// It take ownership over the `wasi_config_t`. #[no_mangle] -pub extern "C" fn wasi_env_new(mut config: Box) -> Option> { +pub unsafe extern "C" fn wasi_env_new( + store: Option<&mut wasm_store_t>, + mut config: Box, +) -> Option> { + let store = &mut store?.inner; + let mut store_mut = store.store_mut(); if !config.inherit_stdout { config.state_builder.stdout(Box::new(Pipe::new())); } @@ -181,10 +185,11 @@ pub extern "C" fn wasi_env_new(mut config: Box) -> Option isize { let inner_buffer = slice::from_raw_parts_mut(buffer as *mut _, buffer_len as usize); - let state = env.inner.state(); + let mut store_mut = env.store.store_mut(); + let state = env.inner.data_mut(&mut store_mut).state(); if let Ok(mut stdout) = state.stdout() { if let Some(stdout) = stdout.as_mut() { @@ -221,7 +227,8 @@ pub unsafe extern "C" fn wasi_env_read_stderr( buffer_len: usize, ) -> isize { let inner_buffer = slice::from_raw_parts_mut(buffer as *mut _, buffer_len as usize); - let state = env.inner.state(); + let mut store_mut = env.store.store_mut(); + let state = env.inner.data_mut(&mut store_mut).state(); if let Ok(mut stderr) = state.stderr() { if let Some(stderr) = stderr.as_mut() { read_inner(stderr, inner_buffer) @@ -320,30 +327,25 @@ pub unsafe extern "C" fn wasi_get_wasi_version(module: &wasm_module_t) -> wasi_v /// implementation ordered as expected by the `wasm_module_t`. #[no_mangle] pub unsafe extern "C" fn wasi_get_imports( - store: Option<&wasm_store_t>, + _store: Option<&wasm_store_t>, + wasi_env: Option<&mut wasi_env_t>, module: Option<&wasm_module_t>, imports: &mut wasm_extern_vec_t, ) -> bool { - wasi_get_imports_inner(store, module, imports).is_some() + wasi_get_imports_inner(wasi_env, module, imports).is_some() } -fn wasi_get_imports_inner( - store: Option<&wasm_store_t>, +unsafe fn wasi_get_imports_inner( + wasi_env: Option<&mut wasi_env_t>, module: Option<&wasm_module_t>, imports: &mut wasm_extern_vec_t, ) -> Option<()> { - let store = store?; - if store.context.is_none() { - crate::error::update_last_error(wasm_store_t::CTX_ERR_STR); - } - let mut ctx = store.context.as_ref()?.borrow_mut(); + let wasi_env = wasi_env?; + let store = &mut wasi_env.store; + let mut store_mut = store.store_mut(); let module = module?; - let version = c_try!(get_wasi_version(&module.inner, false) - .ok_or("could not detect a WASI version on the given module")); - - let inner = unsafe { ctx.inner.transmute_data::() }; - let import_object = generate_import_object_from_ctx(&mut inner.as_context_mut(), version); + let import_object = c_try!(wasi_env.inner.import_object(&mut store_mut, &module.inner)); imports.set_buffer(c_try!(module .inner @@ -358,22 +360,37 @@ fn wasi_get_imports_inner( import_type.name() ) })?; - let inner = Extern::from_vm_extern(&mut ctx.inner, ext.to_vm_extern()); - Ok(Some(Box::new(inner.into()))) + Ok(Some(Box::new(wasm_extern_t::new(store.clone(), ext)))) }) .collect::, String>>())); Some(()) } +#[no_mangle] +pub unsafe extern "C" fn wasi_env_initialize_instance( + wasi_env: &mut wasi_env_t, + store: &mut wasm_store_t, + instance: &mut wasm_instance_t, +) -> bool { + let mem = c_try!(instance.inner.exports.get_memory("memory"); otherwise false); + wasi_env + .inner + .data_mut(&mut store.inner.store_mut()) + .set_memory(mem.clone()); + true +} + #[no_mangle] pub unsafe extern "C" fn wasi_get_start_function( instance: &mut wasm_instance_t, ) -> Option> { let start = c_try!(instance.inner.exports.get_function("_start")); - Some(Box::new(wasm_func_t::new(start.clone()))) + Some(Box::new(wasm_func_t { + extern_: wasm_extern_t::new(instance.store.clone(), start.clone().into()), + })) } #[cfg(test)] @@ -388,7 +405,7 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); + wasmer_funcenv_t* env = wasmer_funcenv_new(store, 0); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_unstable\" \"args_get\" (func (param i32 i32) (result i32))))"); @@ -403,7 +420,7 @@ mod tests { wasm_module_delete(module); wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); - wasm_context_delete(ctx); + wasmer_funcenv_delete(env); wasm_store_delete(store); wasm_engine_delete(engine); @@ -421,7 +438,7 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); + wasmer_funcenv_t* env = wasmer_funcenv_new(store, 0); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_snapshot_preview1\" \"args_get\" (func (param i32 i32) (result i32))))"); @@ -436,7 +453,7 @@ mod tests { wasm_module_delete(module); wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); - wasm_context_delete(ctx); + wasmer_funcenv_delete(env); wasm_store_delete(store); wasm_engine_delete(engine); @@ -454,7 +471,7 @@ mod tests { int main() { wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); + wasmer_funcenv_t* env = wasmer_funcenv_new(store, 0); wasm_byte_vec_t wat; wasmer_byte_vec_new_from_string(&wat, "(module (import \"wasi_snpsht_prvw1\" \"args_get\" (func (param i32 i32) (result i32))))"); @@ -469,7 +486,7 @@ mod tests { wasm_module_delete(module); wasm_byte_vec_delete(&wasm); wasm_byte_vec_delete(&wat); - wasm_context_delete(ctx); + wasmer_funcenv_delete(env); wasm_store_delete(store); wasm_engine_delete(engine); diff --git a/lib/c-api/tests/wasm-c-api/example/callback.c b/lib/c-api/tests/wasm-c-api/example/callback.c index 977ca727a4f..2fddb1634ff 100644 --- a/lib/c-api/tests/wasm-c-api/example/callback.c +++ b/lib/c-api/tests/wasm-c-api/example/callback.c @@ -35,7 +35,7 @@ void wasm_val_print(wasm_val_t val) { // A function to be called from Wasm code. own wasm_trap_t* print_callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); wasm_val_print(args->data[0]); @@ -48,9 +48,9 @@ own wasm_trap_t* print_callback( // A function closure. own wasm_trap_t* closure_callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { - int i = *(int*) wasm_context_ref_mut_get(ctx_mut); + int i = *(int*)env; printf("Calling back closure...\n"); printf("> %d\n", i); @@ -65,9 +65,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - int i = 42; - wasm_context_t* ctx = wasm_context_new(store, &i); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); @@ -102,8 +99,9 @@ int main(int argc, const char* argv[]) { own wasm_functype_t* print_type = wasm_functype_new_1_1(wasm_valtype_new_i32(), wasm_valtype_new_i32()); own wasm_func_t* print_func = wasm_func_new(store, print_type, print_callback); + int i = 42; own wasm_functype_t* closure_type = wasm_functype_new_0_1(wasm_valtype_new_i32()); - own wasm_func_t* closure_func = wasm_func_new(store, closure_type, closure_callback); + own wasm_func_t* closure_func = wasm_func_new_with_env(store, closure_type, closure_callback, &i, NULL); wasm_functype_delete(print_type); wasm_functype_delete(closure_type); diff --git a/lib/c-api/tests/wasm-c-api/example/callback.cc b/lib/c-api/tests/wasm-c-api/example/callback.cc index 27c1b6545d3..957629cabc8 100644 --- a/lib/c-api/tests/wasm-c-api/example/callback.cc +++ b/lib/c-api/tests/wasm-c-api/example/callback.cc @@ -7,22 +7,22 @@ #include "wasm.hh" // Print a Wasm value -auto operator<<(std::ostream& out, const wasm::Value& val) -> std::ostream& { +auto operator<<(std::ostream& out, const wasm::Val& val) -> std::ostream& { switch (val.kind()) { - case wasm::ValueKind::I32: { + case wasm::ValKind::I32: { out << val.i32(); } break; - case wasm::ValueKind::I64: { + case wasm::ValKind::I64: { out << val.i64(); } break; - case wasm::ValueKind::F32: { + case wasm::ValKind::F32: { out << val.f32(); } break; - case wasm::ValueKind::F64: { + case wasm::ValKind::F64: { out << val.f64(); } break; - case wasm::ValueKind::ANYREF: - case wasm::ValueKind::FUNCREF: { + case wasm::ValKind::ANYREF: + case wasm::ValKind::FUNCREF: { if (val.ref() == nullptr) { out << "null"; } else { @@ -35,7 +35,7 @@ auto operator<<(std::ostream& out, const wasm::Value& val) -> std::ostream& { // A function to be called from Wasm code. auto print_callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl << "> " << args[0] << std::endl; results[0] = args[0].copy(); @@ -45,12 +45,12 @@ auto print_callback( // A function closure. auto closure_callback( - void* env, const wasm::vec& args, wasm::vec& results + void* env, const wasm::vec& args, wasm::vec& results ) -> wasm::own { auto i = *reinterpret_cast(env); std::cout << "Calling back closure..." << std::endl; std::cout << "> " << i << std::endl; - results[0] = wasm::Value::i32(static_cast(i)); + results[0] = wasm::Val::i32(static_cast(i)); return nullptr; } @@ -87,8 +87,8 @@ void run() { // Create external print functions. std::cout << "Creating callback..." << std::endl; auto print_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)), - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)) + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)), + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)) ); auto print_func = wasm::Func::make(store, print_type.get(), print_callback); @@ -96,8 +96,8 @@ void run() { std::cout << "Creating closure..." << std::endl; int i = 42; auto closure_type = wasm::FuncType::make( - wasm::ownvec::make(), - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)) + wasm::ownvec::make(), + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)) ); auto closure_func = wasm::Func::make(store, closure_type.get(), closure_callback, &i); @@ -122,8 +122,8 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - auto args = wasm::vec::make(wasm::Value::i32(3), wasm::Value::i32(4)); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Val::i32(3), wasm::Val::i32(4)); + auto results = wasm::vec::make_uninitialized(1); if (run_func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm-c-api/example/finalize.c b/lib/c-api/tests/wasm-c-api/example/finalize.c index 6532c3a6bdb..4f2efc598a2 100644 --- a/lib/c-api/tests/wasm-c-api/example/finalize.c +++ b/lib/c-api/tests/wasm-c-api/example/finalize.c @@ -12,8 +12,8 @@ const int iterations = 100000; int live_count = 0; void finalize(void* data) { - int i = (int)data; - if (i % (iterations / 10) == 0) printf("Finalizing #%d...\n", i); + intptr_t i = (intptr_t)data; + if (i % (iterations / 10) == 0) printf("Finalizing #%" PRIdPTR "...\n", i); --live_count; } @@ -74,8 +74,6 @@ int main(int argc, const char* argv[]) { printf("Live count %d\n", live_count); printf("Creating store 1...\n"); wasm_store_t* store1 = wasm_store_new(engine); - wasm_context_t* ctx1 = wasm_context_new(store1, 0); - wasm_store_context_set(store1, ctx1); printf("Running in store 1...\n"); run_in_store(store1); @@ -83,8 +81,6 @@ int main(int argc, const char* argv[]) { printf("Creating store 2...\n"); wasm_store_t* store2 = wasm_store_new(engine); - wasm_context_t* ctx2 = wasm_context_new(store2, 0); - wasm_store_context_set(store2, ctx2); printf("Running in store 2...\n"); run_in_store(store2); diff --git a/lib/c-api/tests/wasm-c-api/example/global.c b/lib/c-api/tests/wasm-c-api/example/global.c index 2187c5cdd63..5bd403369c3 100644 --- a/lib/c-api/tests/wasm-c-api/example/global.c +++ b/lib/c-api/tests/wasm-c-api/example/global.c @@ -52,8 +52,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/global.cc b/lib/c-api/tests/wasm-c-api/example/global.cc index a1770ef82d1..178eb61f8b7 100644 --- a/lib/c-api/tests/wasm-c-api/example/global.cc +++ b/lib/c-api/tests/wasm-c-api/example/global.cc @@ -31,9 +31,9 @@ void check(T actual, U expected) { } } -auto call(const wasm::Func* func) -> wasm::Value { - auto args = wasm::vec::make(); - auto results = wasm::vec::make_uninitialized(1); +auto call(const wasm::Func* func) -> wasm::Val { + auto args = wasm::vec::make(); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -41,9 +41,9 @@ auto call(const wasm::Func* func) -> wasm::Value { return results[0].copy(); } -void call(const wasm::Func* func, wasm::Value&& arg) { - auto args = wasm::vec::make(std::move(arg)); - auto results = wasm::vec::make(); +void call(const wasm::Func* func, wasm::Val&& arg) { + auto args = wasm::vec::make(std::move(arg)); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -83,17 +83,17 @@ void run() { // Create external globals. std::cout << "Creating globals..." << std::endl; auto const_f32_type = wasm::GlobalType::make( - wasm::ValueType::make(wasm::ValueKind::F32), wasm::Mutability::CONST); + wasm::ValType::make(wasm::ValKind::F32), wasm::Mutability::CONST); auto const_i64_type = wasm::GlobalType::make( - wasm::ValueType::make(wasm::ValueKind::I64), wasm::Mutability::CONST); + wasm::ValType::make(wasm::ValKind::I64), wasm::Mutability::CONST); auto var_f32_type = wasm::GlobalType::make( - wasm::ValueType::make(wasm::ValueKind::F32), wasm::Mutability::VAR); + wasm::ValType::make(wasm::ValKind::F32), wasm::Mutability::VAR); auto var_i64_type = wasm::GlobalType::make( - wasm::ValueType::make(wasm::ValueKind::I64), wasm::Mutability::VAR); - auto const_f32_import = wasm::Global::make(store, const_f32_type.get(), wasm::Value::f32(1)); - auto const_i64_import = wasm::Global::make(store, const_i64_type.get(), wasm::Value::i64(2)); - auto var_f32_import = wasm::Global::make(store, var_f32_type.get(), wasm::Value::f32(3)); - auto var_i64_import = wasm::Global::make(store, var_i64_type.get(), wasm::Value::i64(4)); + wasm::ValType::make(wasm::ValKind::I64), wasm::Mutability::VAR); + auto const_f32_import = wasm::Global::make(store, const_f32_type.get(), wasm::Val::f32(1)); + auto const_i64_import = wasm::Global::make(store, const_i64_type.get(), wasm::Val::i64(2)); + auto var_f32_import = wasm::Global::make(store, var_f32_type.get(), wasm::Val::f32(3)); + auto var_i64_import = wasm::Global::make(store, var_i64_type.get(), wasm::Val::i64(4)); // Instantiate. std::cout << "Instantiating module..." << std::endl; @@ -154,10 +154,10 @@ void run() { check(call(get_var_i64_export).i64(), 8); // Modify variables through API and check again. - var_f32_import->set(wasm::Value::f32(33)); - var_i64_import->set(wasm::Value::i64(34)); - var_f32_export->set(wasm::Value::f32(37)); - var_i64_export->set(wasm::Value::i64(38)); + var_f32_import->set(wasm::Val::f32(33)); + var_i64_import->set(wasm::Val::i64(34)); + var_f32_export->set(wasm::Val::f32(37)); + var_i64_export->set(wasm::Val::i64(38)); check(var_f32_import->get().f32(), 33); check(var_i64_import->get().i64(), 34); @@ -170,10 +170,10 @@ void run() { check(call(get_var_i64_export).i64(), 38); // Modify variables through calls and check again. - call(set_var_f32_import, wasm::Value::f32(73)); - call(set_var_i64_import, wasm::Value::i64(74)); - call(set_var_f32_export, wasm::Value::f32(77)); - call(set_var_i64_export, wasm::Value::i64(78)); + call(set_var_f32_import, wasm::Val::f32(73)); + call(set_var_i64_import, wasm::Val::i64(74)); + call(set_var_f32_export, wasm::Val::f32(77)); + call(set_var_i64_export, wasm::Val::i64(78)); check(var_f32_import->get().f32(), 73); check(var_i64_import->get().i64(), 74); diff --git a/lib/c-api/tests/wasm-c-api/example/hello.c b/lib/c-api/tests/wasm-c-api/example/hello.c index 555cd0a16e1..712f4593140 100644 --- a/lib/c-api/tests/wasm-c-api/example/hello.c +++ b/lib/c-api/tests/wasm-c-api/example/hello.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* hello_callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); printf("> Hello World!\n"); @@ -22,8 +22,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); @@ -43,6 +41,13 @@ int main(int argc, const char* argv[]) { } fclose(file); + // Validate. + printf("Validating module...\n"); + if (!wasm_module_validate(store, &binary)) { + printf("> Error validating module!\n"); + return 1; + } + // Compile. printf("Compiling module...\n"); own wasm_module_t* module = wasm_module_new(store, &binary); diff --git a/lib/c-api/tests/wasm-c-api/example/hello.cc b/lib/c-api/tests/wasm-c-api/example/hello.cc index 94eb567b8c8..c2a73c8745b 100644 --- a/lib/c-api/tests/wasm-c-api/example/hello.cc +++ b/lib/c-api/tests/wasm-c-api/example/hello.cc @@ -38,6 +38,13 @@ void run() { exit(1); } + // Validate. + std::cout << "Validating module..." << std::endl; + if (!wasm::Module::validate(store, binary)) { + std::cout << "> Error validating module!" << std::endl; + exit(1); + } + // Compile. std::cout << "Compiling module..." << std::endl; auto module = wasm::Module::make(store, binary); diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.c b/lib/c-api/tests/wasm-c-api/example/hostref.c index d392e2c9b9c..1e787ab1902 100644 --- a/lib/c-api/tests/wasm-c-api/example/hostref.c +++ b/lib/c-api/tests/wasm-c-api/example/hostref.c @@ -10,7 +10,7 @@ // A function to be called from Wasm code. own wasm_trap_t* callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); printf("> %p\n", @@ -127,8 +127,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/hostref.cc b/lib/c-api/tests/wasm-c-api/example/hostref.cc index f9747b91060..09c239e0c91 100644 --- a/lib/c-api/tests/wasm-c-api/example/hostref.cc +++ b/lib/c-api/tests/wasm-c-api/example/hostref.cc @@ -9,7 +9,7 @@ // A function to be called from Wasm code. auto callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> " << (args[0].ref() ? args[0].ref()->get_host_info() : nullptr) << std::endl; @@ -45,8 +45,8 @@ auto get_export_table(wasm::ownvec& exports, size_t i) -> wasm::Ta void call_r_v(const wasm::Func* func, const wasm::Ref* ref) { std::cout << "call_r_v... " << std::flush; - auto args = wasm::vec::make(wasm::Value::ref(ref ? ref->copy() : wasm::own())); - auto results = wasm::vec::make(); + auto args = wasm::vec::make(wasm::Val::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -56,8 +56,8 @@ void call_r_v(const wasm::Func* func, const wasm::Ref* ref) { auto call_v_r(const wasm::Func* func) -> wasm::own { std::cout << "call_v_r... " << std::flush; - auto args = wasm::vec::make(); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -68,8 +68,8 @@ auto call_v_r(const wasm::Func* func) -> wasm::own { auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own { std::cout << "call_r_r... " << std::flush; - auto args = wasm::vec::make(wasm::Value::ref(ref ? ref->copy() : wasm::own())); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Val::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -80,9 +80,9 @@ auto call_r_r(const wasm::Func* func, const wasm::Ref* ref) -> wasm::own::make( - wasm::Value::i32(i), wasm::Value::ref(ref ? ref->copy() : wasm::own())); - auto results = wasm::vec::make(); + auto args = wasm::vec::make( + wasm::Val::i32(i), wasm::Val::ref(ref ? ref->copy() : wasm::own())); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -92,8 +92,8 @@ void call_ir_v(const wasm::Func* func, int32_t i, const wasm::Ref* ref) { auto call_i_r(const wasm::Func* func, int32_t i) -> wasm::own { std::cout << "call_i_r... " << std::flush; - auto args = wasm::vec::make(wasm::Value::i32(i)); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Val::i32(i)); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error calling function!" << std::endl; exit(1); @@ -144,8 +144,8 @@ void run() { // Create external callback function. std::cout << "Creating callback..." << std::endl; auto callback_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::ANYREF)), - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::ANYREF)) + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::ANYREF)), + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::ANYREF)) ); auto callback_func = wasm::Func::make(store, callback_type.get(), callback); @@ -182,7 +182,7 @@ void run() { check(host1->copy(), host1.get()); check(host2->copy(), host2.get()); - wasm::Value val = wasm::Value::ref(host1->copy()); + wasm::Val val = wasm::Val::ref(host1->copy()); check(val.ref()->copy(), host1.get()); auto ref = val.release_ref(); assert(val.ref() == nullptr); @@ -199,7 +199,7 @@ void run() { check(call_v_r(global_get), nullptr); check(global->get().release_ref(), nullptr); - global->set(wasm::Value(host2->copy())); + global->set(wasm::Val(host2->copy())); check(call_v_r(global_get), host2.get()); check(global->get().release_ref(), host2.get()); diff --git a/lib/c-api/tests/wasm-c-api/example/memory.c b/lib/c-api/tests/wasm-c-api/example/memory.c index 9380a52ab4a..edd4ebadd0b 100644 --- a/lib/c-api/tests/wasm-c-api/example/memory.c +++ b/lib/c-api/tests/wasm-c-api/example/memory.c @@ -98,8 +98,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/memory.cc b/lib/c-api/tests/wasm-c-api/example/memory.cc index 4f0bf20f3e7..6cc36192a85 100644 --- a/lib/c-api/tests/wasm-c-api/example/memory.cc +++ b/lib/c-api/tests/wasm-c-api/example/memory.cc @@ -33,8 +33,8 @@ void check(T actual, U expected) { template void check_ok(const wasm::Func* func, Args... xs) { - auto args = wasm::vec::make(wasm::Value::i32(xs)...); - auto results = wasm::vec::make(); + auto args = wasm::vec::make(wasm::Val::i32(xs)...); + auto results = wasm::vec::make(); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); @@ -43,8 +43,8 @@ void check_ok(const wasm::Func* func, Args... xs) { template void check_trap(const wasm::Func* func, Args... xs) { - auto args = wasm::vec::make(wasm::Value::i32(xs)...); - auto results = wasm::vec::make(); + auto args = wasm::vec::make(wasm::Val::i32(xs)...); + auto results = wasm::vec::make(); if (! func->call(args, results)) { std::cout << "> Error on result, expected trap" << std::endl; exit(1); @@ -53,8 +53,8 @@ void check_trap(const wasm::Func* func, Args... xs) { template auto call(const wasm::Func* func, Args... xs) -> int32_t { - auto args = wasm::vec::make(wasm::Value::i32(xs)...); - auto results = wasm::vec::make_uninitialized(1); + auto args = wasm::vec::make(wasm::Val::i32(xs)...); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm-c-api/example/multi.c b/lib/c-api/tests/wasm-c-api/example/multi.c index 517429d240b..4a31e7e4da5 100644 --- a/lib/c-api/tests/wasm-c-api/example/multi.c +++ b/lib/c-api/tests/wasm-c-api/example/multi.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n> "); printf("> %"PRIu32" %"PRIu64" %"PRIu64" %"PRIu32"\n", @@ -44,8 +44,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/multi.cc b/lib/c-api/tests/wasm-c-api/example/multi.cc index 7c167a727e1..6d083557114 100644 --- a/lib/c-api/tests/wasm-c-api/example/multi.cc +++ b/lib/c-api/tests/wasm-c-api/example/multi.cc @@ -8,7 +8,7 @@ // A function to be called from Wasm code. auto callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; std::cout << "> " << args[0].i32(); @@ -54,11 +54,11 @@ void run() { // Create external print functions. std::cout << "Creating callback..." << std::endl; - auto tuple = wasm::ownvec::make( - wasm::ValueType::make(wasm::ValueKind::I32), - wasm::ValueType::make(wasm::ValueKind::I64), - wasm::ValueType::make(wasm::ValueKind::I64), - wasm::ValueType::make(wasm::ValueKind::I32) + auto tuple = wasm::ownvec::make( + wasm::ValType::make(wasm::ValKind::I32), + wasm::ValType::make(wasm::ValKind::I64), + wasm::ValType::make(wasm::ValKind::I64), + wasm::ValType::make(wasm::ValKind::I32) ); auto callback_type = wasm::FuncType::make(tuple.deep_copy(), tuple.deep_copy()); @@ -84,10 +84,10 @@ void run() { // Call. std::cout << "Calling export..." << std::endl; - auto args = wasm::vec::make( - wasm::Value::i32(1), wasm::Value::i64(2), wasm::Value::i64(3), wasm::Value::i32(4) + auto args = wasm::vec::make( + wasm::Val::i32(1), wasm::Val::i64(2), wasm::Val::i64(3), wasm::Val::i32(4) ); - auto results = wasm::vec::make_uninitialized(4); + auto results = wasm::vec::make_uninitialized(4); if (wasm::own trap = run_func->call(args, results)) { std::cout << "> Error calling function! " << trap->message().get() << std::endl; exit(1); diff --git a/lib/c-api/tests/wasm-c-api/example/reflect.c b/lib/c-api/tests/wasm-c-api/example/reflect.c index 8dc80ef571a..d4383185ff0 100644 --- a/lib/c-api/tests/wasm-c-api/example/reflect.c +++ b/lib/c-api/tests/wasm-c-api/example/reflect.c @@ -87,8 +87,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/serialize.c b/lib/c-api/tests/wasm-c-api/example/serialize.c index 2e28300e9d9..8ea1a379af6 100644 --- a/lib/c-api/tests/wasm-c-api/example/serialize.c +++ b/lib/c-api/tests/wasm-c-api/example/serialize.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* hello_callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); printf("> Hello World!\n"); @@ -22,8 +22,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/start.c b/lib/c-api/tests/wasm-c-api/example/start.c index 9f2e96f4acd..f60c03c6468 100644 --- a/lib/c-api/tests/wasm-c-api/example/start.c +++ b/lib/c-api/tests/wasm-c-api/example/start.c @@ -23,8 +23,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/table.c b/lib/c-api/tests/wasm-c-api/example/table.c index 5aa5b96d929..5e91a34a45d 100644 --- a/lib/c-api/tests/wasm-c-api/example/table.c +++ b/lib/c-api/tests/wasm-c-api/example/table.c @@ -9,7 +9,7 @@ // A function to be called from Wasm code. own wasm_trap_t* neg_callback( - wasm_context_ref_mut_t* ctx_mut, const wasm_val_vec_t* args, wasm_val_vec_t* results + const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); results->data[0].kind = WASM_I32; @@ -78,8 +78,6 @@ int main(int argc, const char* argv[]) { printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); // Load binary. printf("Loading binary...\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/table.cc b/lib/c-api/tests/wasm-c-api/example/table.cc index d937ec9038a..9ddf1d902bf 100644 --- a/lib/c-api/tests/wasm-c-api/example/table.cc +++ b/lib/c-api/tests/wasm-c-api/example/table.cc @@ -9,10 +9,10 @@ // A function to be called from Wasm code. auto neg_callback( - const wasm::vec& args, wasm::vec& results + const wasm::vec& args, wasm::vec& results ) -> wasm::own { std::cout << "Calling back..." << std::endl; - results[0] = wasm::Value(-args[0].i32()); + results[0] = wasm::Val(-args[0].i32()); return nullptr; } @@ -49,10 +49,10 @@ void check(bool success) { } auto call( - const wasm::Func* func, wasm::Value&& arg1, wasm::Value&& arg2 -) -> wasm::Value { - auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); - auto results = wasm::vec::make_uninitialized(1); + const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2 +) -> wasm::Val { + auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); + auto results = wasm::vec::make_uninitialized(1); if (func->call(args, results)) { std::cout << "> Error on result, expected return" << std::endl; exit(1); @@ -60,9 +60,9 @@ auto call( return results[0].copy(); } -void check_trap(const wasm::Func* func, wasm::Value&& arg1, wasm::Value&& arg2) { - auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); - auto results = wasm::vec::make_uninitialized(1); +void check_trap(const wasm::Func* func, wasm::Val&& arg1, wasm::Val&& arg2) { + auto args = wasm::vec::make(std::move(arg1), std::move(arg2)); + auto results = wasm::vec::make_uninitialized(1); if (! func->call(args, results)) { std::cout << "> Error on result, expected trap" << std::endl; exit(1); @@ -119,8 +119,8 @@ void run() { // Create external function. std::cout << "Creating callback..." << std::endl; auto neg_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)), - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)) + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)), + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)) ); auto h = wasm::Func::make(store, neg_type.get(), neg_callback); @@ -132,9 +132,9 @@ void run() { check(table->size(), 2u); check(table->get(0) == nullptr); check(table->get(1) != nullptr); - check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(0)); - check(call(call_indirect, wasm::Value::i32(7), wasm::Value::i32(1)).i32(), 7); - check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(2)); + check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(0)); + check(call(call_indirect, wasm::Val::i32(7), wasm::Val::i32(1)).i32(), 7); + check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(2)); // Mutate table. std::cout << "Mutating table..." << std::endl; @@ -143,9 +143,9 @@ void run() { check(! table->set(2, f)); check(table->get(0) != nullptr); check(table->get(1) == nullptr); - check(call(call_indirect, wasm::Value::i32(7), wasm::Value::i32(0)).i32(), 666); - check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(1)); - check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(2)); + check(call(call_indirect, wasm::Val::i32(7), wasm::Val::i32(0)).i32(), 666); + check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(1)); + check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(2)); // Grow table. std::cout << "Growing table..." << std::endl; @@ -157,10 +157,10 @@ void run() { check(table->get(2) != nullptr); check(table->get(3) != nullptr); check(table->get(4) == nullptr); - check(call(call_indirect, wasm::Value::i32(5), wasm::Value::i32(2)).i32(), 5); - check(call(call_indirect, wasm::Value::i32(6), wasm::Value::i32(3)).i32(), -6); - check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(4)); - check_trap(call_indirect, wasm::Value::i32(0), wasm::Value::i32(5)); + check(call(call_indirect, wasm::Val::i32(5), wasm::Val::i32(2)).i32(), 5); + check(call(call_indirect, wasm::Val::i32(6), wasm::Val::i32(3)).i32(), -6); + check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(4)); + check_trap(call_indirect, wasm::Val::i32(0), wasm::Val::i32(5)); check(table->grow(2, f)); check(table->size(), 7u); @@ -175,7 +175,7 @@ void run() { // TODO(wasm+): Once Wasm allows multiple tables, turn this into import. std::cout << "Creating stand-alone table..." << std::endl; auto tabletype = wasm::TableType::make( - wasm::ValueType::make(wasm::ValueKind::FUNCREF), wasm::Limits(5, 5)); + wasm::ValType::make(wasm::ValKind::FUNCREF), wasm::Limits(5, 5)); auto table2 = wasm::Table::make(store, tabletype.get()); check(table2->size() == 5); check(! table2->grow(1)); diff --git a/lib/c-api/tests/wasm-c-api/example/threads.c b/lib/c-api/tests/wasm-c-api/example/threads.c index ec68abb8930..d70bd1ae55c 100644 --- a/lib/c-api/tests/wasm-c-api/example/threads.c +++ b/lib/c-api/tests/wasm-c-api/example/threads.c @@ -13,7 +13,7 @@ const int N_THREADS = 10; const int N_REPS = 3; // A function to be called from Wasm code. -own wasm_trap_t* callback(wasm_context_ref_mut_t* ctx, const wasm_val_vec_t* args, wasm_val_vec_t* results) { +own wasm_trap_t* callback(const wasm_val_vec_t* args, wasm_val_vec_t* results) { assert(args->data[0].kind == WASM_I32); printf("> Thread %d running\n", args->data[0].of.i32); return NULL; @@ -31,8 +31,6 @@ void* run(void* args_abs) { // Rereate store and module. own wasm_store_t* store = wasm_store_new(args->engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); own wasm_module_t* module = wasm_module_obtain(store, args->module); // Run the example N times. @@ -121,9 +119,6 @@ int main(int argc, const char *argv[]) { // Compile and share. own wasm_store_t* store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); - own wasm_module_t* module = wasm_module_new(store, &binary); if (!module) { printf("> Error compiling module!\n"); diff --git a/lib/c-api/tests/wasm-c-api/example/threads.cc b/lib/c-api/tests/wasm-c-api/example/threads.cc index cde5f3a3676..e130717a0cf 100644 --- a/lib/c-api/tests/wasm-c-api/example/threads.cc +++ b/lib/c-api/tests/wasm-c-api/example/threads.cc @@ -10,9 +10,9 @@ const int N_REPS = 3; // A function to be called from Wasm code. auto callback( - void* env, const wasm::vec& args, wasm::vec& results + void* env, const wasm::vec& args, wasm::vec& results ) -> wasm::own { - assert(args[0].kind() == wasm::ValueKind::I32); + assert(args[0].kind() == wasm::ValKind::I32); std::lock_guard lock(*reinterpret_cast(env)); std::cout << "Thread " << args[0].i32() << " running..." << std::endl; std::cout.flush(); @@ -42,15 +42,15 @@ void run( // Create imports. auto func_type = wasm::FuncType::make( - wasm::ownvec::make(wasm::ValueType::make(wasm::ValueKind::I32)), - wasm::ownvec::make() + wasm::ownvec::make(wasm::ValType::make(wasm::ValKind::I32)), + wasm::ownvec::make() ); auto func = wasm::Func::make(store, func_type.get(), callback, mutex); auto global_type = wasm::GlobalType::make( - wasm::ValueType::make(wasm::ValueKind::I32), wasm::Mutability::CONST); + wasm::ValType::make(wasm::ValKind::I32), wasm::Mutability::CONST); auto global = wasm::Global::make( - store, global_type.get(), wasm::Value::i32(i)); + store, global_type.get(), wasm::Val::i32(i)); // Instantiate. auto imports = wasm::vec::make(func.get(), global.get()); @@ -71,7 +71,7 @@ void run( auto run_func = exports[0]->func(); // Call. - auto empty = wasm::vec::make(); + auto empty = wasm::vec::make(); run_func->call(empty, empty); } } diff --git a/lib/c-api/tests/wasm-c-api/example/trap.c b/lib/c-api/tests/wasm-c-api/example/trap.c index 974100d9818..e53e29b233b 100644 --- a/lib/c-api/tests/wasm-c-api/example/trap.c +++ b/lib/c-api/tests/wasm-c-api/example/trap.c @@ -7,16 +7,14 @@ #define own -wasm_store_t* store = NULL; - // A function to be called from Wasm code. own wasm_trap_t* fail_callback( - wasm_context_ref_mut_t* ctx, const wasm_val_vec_t* args, wasm_val_vec_t* results + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results ) { printf("Calling back...\n"); own wasm_name_t message; wasm_name_new_from_string_nt(&message, "callback abort"); - own wasm_trap_t* trap = wasm_trap_new(store, &message); + own wasm_trap_t* trap = wasm_trap_new((wasm_store_t*)env, &message); wasm_name_delete(&message); return trap; } @@ -36,9 +34,7 @@ int main(int argc, const char* argv[]) { // Initialize. printf("Initializing...\n"); wasm_engine_t* engine = wasm_engine_new(); - store = wasm_store_new(engine); - wasm_context_t* ctx = wasm_context_new(store, 0); - wasm_store_context_set(store, ctx); + wasm_store_t* store = wasm_store_new(engine); // Load binary. printf("Loading binary...\n"); @@ -73,7 +69,12 @@ int main(int argc, const char* argv[]) { own wasm_functype_t* fail_type = wasm_functype_new_0_1(wasm_valtype_new_i32()); own wasm_func_t* fail_func = - wasm_func_new(store, fail_type, fail_callback); + wasm_func_new_with_env(store, fail_type, fail_callback, store, NULL); + + if (!fail_func) { + printf("> Error compiling fail_func!\n"); + return 1; + } wasm_functype_delete(fail_type); diff --git a/lib/c-api/tests/wasm-c-api/include/wasm.h b/lib/c-api/tests/wasm-c-api/include/wasm.h index 3c163d890f5..78c9e727586 100644 --- a/lib/c-api/tests/wasm-c-api/include/wasm.h +++ b/lib/c-api/tests/wasm-c-api/include/wasm.h @@ -143,15 +143,6 @@ WASM_DECLARE_OWN(store) WASM_API_EXTERN own wasm_store_t* wasm_store_new(wasm_engine_t*); -// Context - -WASM_DECLARE_OWN(context) -WASM_DECLARE_OWN(context_ref_mut) - -WASM_API_EXTERN own void wasm_store_context_set(own wasm_store_t*, own wasm_context_t*); -WASM_API_EXTERN own void wasm_store_data_set(own wasm_store_t*, own void*); -WASM_API_EXTERN own void* wasm_store_data_get(own wasm_store_t*); - /////////////////////////////////////////////////////////////////////////////// // Type Representations @@ -422,10 +413,15 @@ WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const WASM_DECLARE_REF(func) typedef own wasm_trap_t* (*wasm_func_callback_t)( - wasm_context_ref_mut_t*, const wasm_val_vec_t* args, own wasm_val_vec_t* results); + const wasm_val_vec_t* args, own wasm_val_vec_t* results); +typedef own wasm_trap_t* (*wasm_func_callback_with_env_t)( + void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results); WASM_API_EXTERN own wasm_func_t* wasm_func_new( wasm_store_t*, const wasm_functype_t*, wasm_func_callback_t); +WASM_API_EXTERN own wasm_func_t* wasm_func_new_with_env( + wasm_store_t*, const wasm_functype_t* type, wasm_func_callback_with_env_t, + void* env, void (*finalizer)(void*)); WASM_API_EXTERN own wasm_functype_t* wasm_func_type(const wasm_func_t*); WASM_API_EXTERN size_t wasm_func_param_arity(const wasm_func_t*); diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index 128fd1c7a10..d6f4de250a0 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -7,7 +7,7 @@ use crate::warning; use anyhow::{anyhow, Context, Result}; use std::path::PathBuf; use std::str::FromStr; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::*; #[cfg(feature = "cache")] use wasmer_cache::{Cache, FileSystemCache, Hash}; @@ -97,21 +97,17 @@ impl Run { }) } - fn inner_run(&self, mut ctx: WasmerContext, instance: Instance) -> Result<()> { - let module = self.get_module()?; + fn inner_module_run(&self, mut store: Store, instance: Instance) -> Result<()> { // If this module exports an _initialize function, run that first. if let Ok(initialize) = instance.exports.get_function("_initialize") { initialize - .call(&mut ctx, &[]) + .call(&mut store, &[]) .with_context(|| "failed to run _initialize function")?; } // Do we want to invoke a function? if let Some(ref invoke) = self.invoke { - let imports = imports! {}; - let instance = Instance::new(&mut ctx, &module, &imports)?; - let result = - self.invoke_function(&mut ctx.as_context_mut(), &instance, invoke, &self.args)?; + let result = self.invoke_function(&mut store, &instance, invoke, &self.args)?; println!( "{}", result @@ -122,7 +118,7 @@ impl Run { ); } else { let start: Function = self.try_find_function(&instance, "_start", &[])?; - let result = start.call(&mut ctx, &[]); + let result = start.call(&mut store, &[]); #[cfg(feature = "wasi")] self.wasi.handle_result(result)?; #[cfg(not(feature = "wasi"))] @@ -133,7 +129,7 @@ impl Run { } fn inner_execute(&self) -> Result<()> { - let module = self.get_module()?; + let (mut store, module) = self.get_store_module()?; #[cfg(feature = "emscripten")] { use wasmer_emscripten::{ @@ -143,18 +139,14 @@ impl Run { // TODO: refactor this if is_emscripten_module(&module) { // create an EmEnv with default global - let mut ctx = WasmerContext::new(module.store(), EmEnv::new()); - let mut emscripten_globals = EmscriptenGlobals::new(ctx.as_context_mut(), &module) + let env = FunctionEnv::new(&mut store, EmEnv::new()); + let mut emscripten_globals = EmscriptenGlobals::new(&mut store, &env, &module) .map_err(|e| anyhow!("{}", e))?; - ctx.data_mut() + env.as_mut(&mut store) .set_data(&emscripten_globals.data, Default::default()); let import_object = - generate_emscripten_env(&mut ctx.as_context_mut(), &mut emscripten_globals); - let mut instance = match Instance::new( - &mut ctx.as_context_mut(), - &module, - &import_object, - ) { + generate_emscripten_env(&mut store, &env, &mut emscripten_globals); + let mut instance = match Instance::new(&mut store, &module, &import_object) { Ok(instance) => instance, Err(e) => { let err: Result<(), _> = Err(e); @@ -170,7 +162,7 @@ impl Run { run_emscripten_instance( &mut instance, - ctx.as_context_mut(), + env.into_mut(&mut store), &mut emscripten_globals, if let Some(cn) = &self.command_name { cn @@ -219,37 +211,35 @@ impl Run { .map(|f| f.to_string_lossy().to_string()) }) .unwrap_or_default(); - let (ctx, instance) = self + let (_ctx, instance) = self .wasi - .instantiate(&module, program_name, self.args.clone()) + .instantiate(&mut store, &module, program_name, self.args.clone()) .with_context(|| "failed to instantiate WASI module")?; - self.inner_run(ctx, instance) + self.inner_module_run(store, instance) } // not WASI _ => { - let mut ctx = WasmerContext::new(module.store(), ()); - let instance = Instance::new(&mut ctx, &module, &imports! {})?; - self.inner_run(ctx, instance) + let instance = Instance::new(&mut store, &module, &imports! {})?; + self.inner_module_run(store, instance) } } }; #[cfg(not(feature = "wasi"))] let ret = { - let mut ctx = WasmerContext::new(module.store(), ()); - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let instance = Instance::new(&mut store, &module, &imports! {})?; self.inner_run(ctx, instance) }; ret } - fn get_module(&self) -> Result { + fn get_store_module(&self) -> Result<(Store, Module)> { let contents = std::fs::read(self.path.clone())?; if wasmer_compiler::UniversalArtifact::is_deserializable(&contents) { let engine = wasmer_compiler::Universal::headless().engine(); let store = Store::new_with_engine(&engine); let module = unsafe { Module::deserialize_from_file(&store, &self.path)? }; - return Ok(module); + return Ok((store, module)); } let (store, compiler_type) = self.store.get_store()?; #[cfg(feature = "cache")] @@ -270,7 +260,7 @@ impl Run { // We set the name outside the cache, to make sure we dont cache the name module.set_name(&self.path.file_name().unwrap_or_default().to_string_lossy()); - Ok(module) + Ok((store, module)) } #[cfg(feature = "cache")] @@ -375,7 +365,7 @@ impl Run { fn invoke_function( &self, - ctx: &mut impl AsContextMut, + ctx: &mut impl AsStoreMut, instance: &Instance, invoke: &str, args: &[String], diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index 5cf8287edde..3a0121a2069 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -2,7 +2,7 @@ use crate::utils::{parse_envvar, parse_mapdir}; use anyhow::Result; use std::collections::BTreeSet; use std::path::PathBuf; -use wasmer::{AsContextMut, Context, Instance, Module, RuntimeError, Value}; +use wasmer::{AsStoreMut, FunctionEnv, Instance, Module, RuntimeError, Value}; use wasmer_wasi::{ get_wasi_versions, import_object_for_all_wasi_versions, is_wasix_module, WasiEnv, WasiError, WasiState, WasiVersion, @@ -78,10 +78,11 @@ impl Wasi { /// Helper function for instantiating a module with Wasi imports for the `Run` command. pub fn instantiate( &self, + store: &mut impl AsStoreMut, module: &Module, program_name: String, args: Vec, - ) -> Result<(Context, Instance)> { + ) -> Result<(FunctionEnv, Instance)> { let args = args.iter().cloned().map(|arg| arg.into_bytes()); let mut wasi_state_builder = WasiState::new(program_name); @@ -99,17 +100,16 @@ impl Wasi { } } - let wasi_env = wasi_state_builder.finalize()?; - wasi_env.state.fs.is_wasix.store( + let wasi_env = wasi_state_builder.finalize(store)?; + wasi_env.env.as_mut(store).state.fs.is_wasix.store( is_wasix_module(module), std::sync::atomic::Ordering::Release, ); - let mut ctx = Context::new(module.store(), wasi_env); - let import_object = import_object_for_all_wasi_versions(&mut ctx.as_context_mut()); - let instance = Instance::new(&mut ctx, module, &import_object)?; + let import_object = import_object_for_all_wasi_versions(store, &wasi_env.env); + let instance = Instance::new(store, module, &import_object)?; let memory = instance.exports.get_memory("memory")?; - ctx.data_mut().set_memory(memory.clone()); - Ok((ctx, instance)) + wasi_env.data_mut(store).set_memory(memory.clone()); + Ok((wasi_env.env, instance)) } /// Helper function for handling the result of a Wasi _start function. diff --git a/lib/cli/src/commands/wast.rs b/lib/cli/src/commands/wast.rs index 5dd0352c4d1..580bdb205e1 100644 --- a/lib/cli/src/commands/wast.rs +++ b/lib/cli/src/commands/wast.rs @@ -3,7 +3,6 @@ use crate::store::StoreOptions; use anyhow::{Context, Result}; use std::path::PathBuf; use structopt::StructOpt; -use wasmer::Context as WasmerContext; use wasmer_wast::Wast as WastSpectest; #[derive(Debug, StructOpt)] @@ -29,8 +28,7 @@ impl Wast { } fn inner_execute(&self) -> Result<()> { let (store, _compiler_name) = self.store.get_store()?; - let ctx = WasmerContext::new(&store, ()); - let mut wast = WastSpectest::new_with_spectest(ctx); + let mut wast = WastSpectest::new_with_spectest(store); wast.fail_fast = self.fail_fast; wast.run_file(&self.path).with_context(|| "tests failed")?; eprintln!("Wast tests succeeded for `{}`.", self.path.display()); diff --git a/lib/compiler-cranelift/README.md b/lib/compiler-cranelift/README.md index 716e9ddea47..f05e66420d3 100644 --- a/lib/compiler-cranelift/README.md +++ b/lib/compiler-cranelift/README.md @@ -10,7 +10,7 @@ use wasmer_compiler_cranelift::Cranelift; let compiler = Cranelift::new(); // Put it into an engine and add it to the store -let store = Store::new_with_engine(&Universal::new(compiler).engine()); +let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); ``` *Note: you can find a [full working example using Cranelift compiler diff --git a/lib/compiler-cranelift/src/translator/func_environ.rs b/lib/compiler-cranelift/src/translator/func_environ.rs index dbd83d00217..0ca674269ca 100644 --- a/lib/compiler-cranelift/src/translator/func_environ.rs +++ b/lib/compiler-cranelift/src/translator/func_environ.rs @@ -2,7 +2,7 @@ // Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md //! All the runtime support necessary for the wasm to cranelift translation is formalized by the -//! traits `FunctionEnvironment`. +//! traits `FunctionEnvMutironment`. use super::func_state::FuncTranslationState; use super::translation_utils::reference_type; @@ -449,7 +449,7 @@ pub trait FuncEnvironment: TargetEnvironment { Ok(()) } - /// Optional callback for the `FunctionEnvironment` performing this translation to maintain + /// Optional callback for the `FunctionEnvMutironment` performing this translation to maintain /// internal state or prepare custom state for the operator to translate fn before_translate_operator( &mut self, @@ -460,7 +460,7 @@ pub trait FuncEnvironment: TargetEnvironment { Ok(()) } - /// Optional callback for the `FunctionEnvironment` performing this translation to maintain + /// Optional callback for the `FunctionEnvMutironment` performing this translation to maintain /// internal state or finalize custom state for the operator that was translated fn after_translate_operator( &mut self, diff --git a/lib/compiler-llvm/README.md b/lib/compiler-llvm/README.md index 782784b0b11..664b80e090e 100644 --- a/lib/compiler-llvm/README.md +++ b/lib/compiler-llvm/README.md @@ -10,7 +10,7 @@ use wasmer_compiler_llvm::LLVM; let compiler = LLVM::new(); // Put it into an engine and add it to the store -let store = Store::new_with_engine(&Universal::new(compiler).engine()); +let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); ``` *Note: you can find a [full working example using LLVM compiler here][example].* diff --git a/lib/compiler-llvm/src/translator/intrinsics.rs b/lib/compiler-llvm/src/translator/intrinsics.rs index 9b3c6ba8be3..7a1d1ebb9ba 100644 --- a/lib/compiler-llvm/src/translator/intrinsics.rs +++ b/lib/compiler-llvm/src/translator/intrinsics.rs @@ -1686,7 +1686,7 @@ pub fn tbaa_label<'ctx>( let context = module.get_context(); - // TODO: ContextRef can't return us the lifetime from module through Deref. + // TODO: StoreRef can't return us the lifetime from module through Deref. // This could be fixed once generic_associated_types is stable. let context = { let context2 = &*context; diff --git a/lib/compiler-singlepass/README.md b/lib/compiler-singlepass/README.md index 56226839c84..84ff8430b81 100644 --- a/lib/compiler-singlepass/README.md +++ b/lib/compiler-singlepass/README.md @@ -10,7 +10,7 @@ use wasmer_compiler_singlepass::Singlepass; let compiler = Singlepass::new(); // Put it into an engine and add it to the store -let store = Store::new_with_engine(&Universal::new(compiler).engine()); +let mut store = Store::new_with_engine(&Universal::new(compiler).engine()); ``` *Note: you can find a [full working example using Singlepass compiler diff --git a/lib/compiler/src/engine/artifact.rs b/lib/compiler/src/engine/artifact.rs index 00d3924f585..f557bc5ca64 100644 --- a/lib/compiler/src/engine/artifact.rs +++ b/lib/compiler/src/engine/artifact.rs @@ -4,7 +4,7 @@ use crate::{ArtifactCreate, Upcastable}; use wasmer_types::entity::BoxedSlice; use wasmer_types::{DataInitializer, FunctionIndex, LocalFunctionIndex, SignatureIndex}; use wasmer_vm::{ - ContextObjects, FunctionBodyPtr, InstanceAllocator, InstanceHandle, TrapHandler, VMExtern, + FunctionBodyPtr, InstanceAllocator, InstanceHandle, StoreObjects, TrapHandlerFn, VMExtern, VMSharedSignatureIndex, VMTrampoline, }; @@ -51,7 +51,7 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { &self, tunables: &dyn Tunables, imports: &[VMExtern], - context: &mut ContextObjects, + context: &mut StoreObjects, ) -> Result { // Validate the CPU features this module was compiled with against the // host CPU features. @@ -128,7 +128,7 @@ pub trait Artifact: Send + Sync + Upcastable + ArtifactCreate { /// See [`InstanceHandle::finish_instantiation`]. unsafe fn finish_instantiation( &self, - trap_handler: &(dyn TrapHandler + 'static), + trap_handler: Option<*const TrapHandlerFn<'static>>, handle: &mut InstanceHandle, ) -> Result<(), InstantiationError> { let data_initializers = self diff --git a/lib/compiler/src/engine/resolver.rs b/lib/compiler/src/engine/resolver.rs index 3835766aa19..a97044adb8b 100644 --- a/lib/compiler/src/engine/resolver.rs +++ b/lib/compiler/src/engine/resolver.rs @@ -8,7 +8,7 @@ use wasmer_types::{ }; use wasmer_vm::{ - ContextObjects, FunctionBodyPtr, Imports, MemoryStyle, TableStyle, VMExtern, VMFunctionBody, + FunctionBodyPtr, Imports, MemoryStyle, StoreObjects, TableStyle, VMExtern, VMFunctionBody, VMFunctionImport, VMFunctionKind, VMGlobalImport, VMMemoryImport, VMTableImport, }; @@ -35,7 +35,7 @@ fn get_extern_from_import(module: &ModuleInfo, import_index: &ImportIndex) -> Ex } /// Get an `ExternType` given an export (and Engine signatures in case is a function). -fn get_extern_type(context: &ContextObjects, extern_: &VMExtern) -> ExternType { +fn get_extern_type(context: &StoreObjects, extern_: &VMExtern) -> ExternType { match extern_ { VMExtern::Function(f) => ExternType::Function(f.get(context).signature.clone()), VMExtern::Table(t) => ExternType::Table(*t.get(context).ty()), @@ -54,7 +54,7 @@ fn get_extern_type(context: &ContextObjects, extern_: &VMExtern) -> ExternType { pub fn resolve_imports( module: &ModuleInfo, imports: &[VMExtern], - context: &ContextObjects, + context: &StoreObjects, finished_dynamic_function_trampolines: &BoxedSlice, memory_styles: &PrimaryMap, _table_styles: &PrimaryMap, diff --git a/lib/compiler/src/engine/tunables.rs b/lib/compiler/src/engine/tunables.rs index 43d7c1a2d39..207ceec9dca 100644 --- a/lib/compiler/src/engine/tunables.rs +++ b/lib/compiler/src/engine/tunables.rs @@ -5,7 +5,7 @@ use wasmer_types::{ GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType, ModuleInfo, TableIndex, TableType, }; -use wasmer_vm::{ContextObjects, InternalContextHandle, MemoryError}; +use wasmer_vm::{InternalStoreHandle, MemoryError, StoreObjects}; use wasmer_vm::{MemoryStyle, TableStyle}; use wasmer_vm::{VMGlobal, VMMemory, VMTable}; use wasmer_vm::{VMMemoryDefinition, VMTableDefinition}; @@ -62,11 +62,11 @@ pub trait Tunables { /// - `memory_definition_locations` must point to a valid locations in VM memory. unsafe fn create_memories( &self, - context: &mut ContextObjects, + context: &mut StoreObjects, module: &ModuleInfo, memory_styles: &PrimaryMap, memory_definition_locations: &[NonNull], - ) -> Result>, LinkError> { + ) -> Result>, LinkError> { let num_imports = module.num_imported_memories; let mut memories: PrimaryMap = PrimaryMap::with_capacity(module.memories.len() - num_imports); @@ -79,7 +79,7 @@ pub trait Tunables { let mi = MemoryIndex::new(index); let ty = &module.memories[mi]; let style = &memory_styles[mi]; - memories.push(InternalContextHandle::new( + memories.push(InternalStoreHandle::new( context, self.create_vm_memory(ty, style, *mdl) .map_err(|e| LinkError::Resource(format!("Failed to create memory: {}", e)))?, @@ -95,11 +95,11 @@ pub trait Tunables { /// To be done unsafe fn create_tables( &self, - context: &mut ContextObjects, + context: &mut StoreObjects, module: &ModuleInfo, table_styles: &PrimaryMap, table_definition_locations: &[NonNull], - ) -> Result>, LinkError> { + ) -> Result>, LinkError> { let num_imports = module.num_imported_tables; let mut tables: PrimaryMap = PrimaryMap::with_capacity(module.tables.len() - num_imports); @@ -112,7 +112,7 @@ pub trait Tunables { let ti = TableIndex::new(index); let ty = &module.tables[ti]; let style = &table_styles[ti]; - tables.push(InternalContextHandle::new( + tables.push(InternalStoreHandle::new( context, self.create_vm_table(ty, style, *tdl) .map_err(LinkError::Resource)?, @@ -125,14 +125,14 @@ pub trait Tunables { /// with initializers applied. fn create_globals( &self, - context: &mut ContextObjects, + context: &mut StoreObjects, module: &ModuleInfo, - ) -> Result>, LinkError> { + ) -> Result>, LinkError> { let num_imports = module.num_imported_globals; let mut vmctx_globals = PrimaryMap::with_capacity(module.globals.len() - num_imports); for &global_type in module.globals.values().skip(num_imports) { - vmctx_globals.push(InternalContextHandle::new( + vmctx_globals.push(InternalStoreHandle::new( context, self.create_global(global_type) .map_err(LinkError::Resource)?, diff --git a/lib/emscripten/src/bitwise.rs b/lib/emscripten/src/bitwise.rs index be6ee40be01..d912fda7daa 100644 --- a/lib/emscripten/src/bitwise.rs +++ b/lib/emscripten/src/bitwise.rs @@ -1,9 +1,9 @@ use crate::emscripten_target; use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; ///emscripten: _llvm_bswap_i64 -pub fn _llvm_bswap_i64(ctx: ContextMut<'_, EmEnv>, _low: i32, high: i32) -> i32 { +pub fn _llvm_bswap_i64(ctx: FunctionEnvMut, _low: i32, high: i32) -> i32 { debug!("emscripten::_llvm_bswap_i64"); emscripten_target::setTempRet0(ctx, _low.swap_bytes()); high.swap_bytes() diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs index 4bf614c40f1..736313d638d 100644 --- a/lib/emscripten/src/emscripten_target.rs +++ b/lib/emscripten/src/emscripten_target.rs @@ -4,33 +4,33 @@ use crate::env::{get_emscripten_data, get_emscripten_funcs}; use crate::EmEnv; #[cfg(target_os = "linux")] use libc::getdtablesize; -use wasmer::{AsContextMut, ContextMut}; +use wasmer::FunctionEnvMut; -pub fn asm_const_i(_ctx: ContextMut<'_, EmEnv>, _val: i32) -> i32 { +pub fn asm_const_i(_ctx: FunctionEnvMut, _val: i32) -> i32 { debug!("emscripten::asm_const_i: {}", _val); 0 } -pub fn exit_with_live_runtime(_ctx: ContextMut<'_, EmEnv>) { +pub fn exit_with_live_runtime(_ctx: FunctionEnvMut) { debug!("emscripten::exit_with_live_runtime"); } -pub fn setTempRet0(ctx: ContextMut<'_, EmEnv>, val: i32) { +pub fn setTempRet0(ctx: FunctionEnvMut, val: i32) { trace!("emscripten::setTempRet0: {}", val); get_emscripten_data(&ctx).as_mut().unwrap().temp_ret_0 = val; } -pub fn getTempRet0(ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn getTempRet0(ctx: FunctionEnvMut) -> i32 { trace!("emscripten::getTempRet0"); get_emscripten_data(&ctx).as_ref().unwrap().temp_ret_0 } -pub fn _alarm(_ctx: ContextMut<'_, EmEnv>, _seconds: u32) -> i32 { +pub fn _alarm(_ctx: FunctionEnvMut, _seconds: u32) -> i32 { debug!("emscripten::_alarm({})", _seconds); 0 } -pub fn _atexit(_ctx: ContextMut<'_, EmEnv>, _func: i32) -> i32 { +pub fn _atexit(_ctx: FunctionEnvMut, _func: i32) -> i32 { debug!("emscripten::_atexit"); // TODO: implement atexit properly // __ATEXIT__.unshift({ @@ -39,38 +39,38 @@ pub fn _atexit(_ctx: ContextMut<'_, EmEnv>, _func: i32) -> i32 { // }); 0 } -pub fn __Unwind_Backtrace(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn __Unwind_Backtrace(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::__Unwind_Backtrace"); 0 } -pub fn __Unwind_FindEnclosingFunction(_ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn __Unwind_FindEnclosingFunction(_ctx: FunctionEnvMut, _a: i32) -> i32 { debug!("emscripten::__Unwind_FindEnclosingFunction"); 0 } -pub fn __Unwind_GetIPInfo(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn __Unwind_GetIPInfo(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::__Unwind_GetIPInfo"); 0 } -pub fn ___cxa_find_matching_catch_2(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn ___cxa_find_matching_catch_2(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::___cxa_find_matching_catch_2"); 0 } -pub fn ___cxa_find_matching_catch_3(_ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn ___cxa_find_matching_catch_3(_ctx: FunctionEnvMut, _a: i32) -> i32 { debug!("emscripten::___cxa_find_matching_catch_3"); 0 } -pub fn ___cxa_free_exception(_ctx: ContextMut<'_, EmEnv>, _a: i32) { +pub fn ___cxa_free_exception(_ctx: FunctionEnvMut, _a: i32) { debug!("emscripten::___cxa_free_exception"); } -pub fn ___resumeException(_ctx: ContextMut<'_, EmEnv>, _a: i32) { +pub fn ___resumeException(_ctx: FunctionEnvMut, _a: i32) { debug!("emscripten::___resumeException"); } -pub fn _dladdr(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _dladdr(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::_dladdr"); 0 } pub fn ___gxx_personality_v0( - _ctx: ContextMut<'_, EmEnv>, + _ctx: FunctionEnvMut, _a: i32, _b: i32, _c: i32, @@ -83,25 +83,25 @@ pub fn ___gxx_personality_v0( } #[cfg(target_os = "linux")] -pub fn _getdtablesize(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn _getdtablesize(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::getdtablesize"); unsafe { getdtablesize() } } #[cfg(not(target_os = "linux"))] -pub fn _getdtablesize(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn _getdtablesize(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::getdtablesize"); -1 } -pub fn _gethostbyaddr(_ctx: ContextMut<'_, EmEnv>, _addr: i32, _addrlen: i32, _atype: i32) -> i32 { +pub fn _gethostbyaddr(_ctx: FunctionEnvMut, _addr: i32, _addrlen: i32, _atype: i32) -> i32 { debug!("emscripten::gethostbyaddr"); 0 } -pub fn _gethostbyname(_ctx: ContextMut<'_, EmEnv>, _name: i32) -> i32 { +pub fn _gethostbyname(_ctx: FunctionEnvMut, _name: i32) -> i32 { debug!("emscripten::gethostbyname_r"); 0 } pub fn _gethostbyname_r( - _ctx: ContextMut<'_, EmEnv>, + _ctx: FunctionEnvMut, _name: i32, _ret: i32, _buf: i32, @@ -113,13 +113,13 @@ pub fn _gethostbyname_r( 0 } // NOTE: php.js has proper impl; libc has proper impl for linux -pub fn _getloadavg(_ctx: ContextMut<'_, EmEnv>, _loadavg: i32, _nelem: i32) -> i32 { +pub fn _getloadavg(_ctx: FunctionEnvMut, _loadavg: i32, _nelem: i32) -> i32 { debug!("emscripten::getloadavg"); 0 } #[allow(clippy::too_many_arguments)] pub fn _getnameinfo( - _ctx: ContextMut<'_, EmEnv>, + _ctx: FunctionEnvMut, _addr: i32, _addrlen: i32, _host: i32, @@ -142,7 +142,7 @@ pub fn _getnameinfo( macro_rules! invoke { ($ctx: ident, $name:ident, $name_ref:ident, $( $arg:ident ),*) => {{ let funcs = get_emscripten_funcs(&$ctx).clone(); - let sp = funcs.stack_save_ref().expect("stack_save is None").call(&mut $ctx.as_context_mut()).expect("stack_save call failed"); + let sp = funcs.stack_save_ref().expect("stack_save is None").call(&mut $ctx).expect("stack_save call failed"); let call = funcs.$name_ref().expect(concat!("Dynamic call is None: ", stringify!($name))).clone(); match call.call(&mut $ctx, $($arg),*) { Ok(v) => v, @@ -183,50 +183,50 @@ macro_rules! invoke_no_stack_save { let funcs = get_emscripten_funcs(&$ctx).clone(); let call = funcs.$name_ref().expect(concat!(stringify!($name), " is set to None")).clone(); - call.call(&mut $ctx.as_context_mut(), $($arg),*).unwrap() + call.call(&mut $ctx, $($arg),*).unwrap() }} } // Invoke functions -pub fn invoke_i(mut ctx: ContextMut<'_, EmEnv>, index: i32) -> i32 { +pub fn invoke_i(mut ctx: FunctionEnvMut, index: i32) -> i32 { debug!("emscripten::invoke_i"); invoke!(ctx, dyn_call_i, dyn_call_i_ref, index) } -pub fn invoke_ii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32) -> i32 { +pub fn invoke_ii(mut ctx: FunctionEnvMut, index: i32, a1: i32) -> i32 { debug!("emscripten::invoke_ii"); invoke!(ctx, dyn_call_ii, dyn_call_ii_ref, index, a1) } -pub fn invoke_iii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) -> i32 { +pub fn invoke_iii(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32) -> i32 { debug!("emscripten::invoke_iii"); invoke!(ctx, dyn_call_iii, dyn_call_iii_ref, index, a1, a2) } -pub fn invoke_iiii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_iiii(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_iiii"); invoke!(ctx, dyn_call_iiii, dyn_call_iiii_ref, index, a1, a2, a3) } -pub fn invoke_iifi(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: f64, a3: i32) -> i32 { +pub fn invoke_iifi(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: f64, a3: i32) -> i32 { debug!("emscripten::invoke_iifi"); invoke!(ctx, dyn_call_iifi, dyn_call_iifi_ref, index, a1, a2, a3) } -pub fn invoke_v(mut ctx: ContextMut<'_, EmEnv>, index: i32) { +pub fn invoke_v(mut ctx: FunctionEnvMut, index: i32) { debug!("emscripten::invoke_v"); invoke_no_return!(ctx, dyn_call_v, dyn_call_v_ref, index); } -pub fn invoke_vi(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32) { +pub fn invoke_vi(mut ctx: FunctionEnvMut, index: i32, a1: i32) { debug!("emscripten::invoke_vi"); invoke_no_return!(ctx, dyn_call_vi, dyn_call_vi_ref, index, a1); } -pub fn invoke_vii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) { +pub fn invoke_vii(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32) { debug!("emscripten::invoke_vii"); invoke_no_return!(ctx, dyn_call_vii, dyn_call_vii_ref, index, a1, a2); } -pub fn invoke_viii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) { +pub fn invoke_viii(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32) { debug!("emscripten::invoke_viii"); invoke_no_return!(ctx, dyn_call_viii, dyn_call_viii_ref, index, a1, a2, a3); } pub fn invoke_viiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -245,12 +245,12 @@ pub fn invoke_viiii( a4 ); } -pub fn invoke_dii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) -> f64 { +pub fn invoke_dii(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32) -> f64 { debug!("emscripten::invoke_dii"); invoke!(ctx, dyn_call_dii, dyn_call_dii_ref, index, a1, a2) } pub fn invoke_diiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -270,7 +270,7 @@ pub fn invoke_diiii( ) } pub fn invoke_iiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -290,7 +290,7 @@ pub fn invoke_iiiii( ) } pub fn invoke_iiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -313,7 +313,7 @@ pub fn invoke_iiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -338,7 +338,7 @@ pub fn invoke_iiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -365,7 +365,7 @@ pub fn invoke_iiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -394,7 +394,7 @@ pub fn invoke_iiiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -425,7 +425,7 @@ pub fn invoke_iiiiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_iiiiiiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -456,12 +456,12 @@ pub fn invoke_iiiiiiiiiii( a10 ) } -pub fn invoke_vd(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: f64) { +pub fn invoke_vd(mut ctx: FunctionEnvMut, index: i32, a1: f64) { debug!("emscripten::invoke_vd"); invoke_no_return!(ctx, dyn_call_vd, dyn_call_vd_ref, index, a1) } pub fn invoke_viiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -484,7 +484,7 @@ pub fn invoke_viiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -509,7 +509,7 @@ pub fn invoke_viiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -536,7 +536,7 @@ pub fn invoke_viiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -565,7 +565,7 @@ pub fn invoke_viiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -596,7 +596,7 @@ pub fn invoke_viiiiiiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiiiiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -628,18 +628,18 @@ pub fn invoke_viiiiiiiiii( ) } -pub fn invoke_iij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_iij(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_iij"); invoke!(ctx, dyn_call_iij, dyn_call_iij_ref, index, a1, a2, a3) } -pub fn invoke_iji(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_iji(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_iji"); invoke!(ctx, dyn_call_iji, dyn_call_iji_ref, index, a1, a2, a3) } pub fn invoke_iiji( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -652,7 +652,7 @@ pub fn invoke_iiji( #[allow(clippy::too_many_arguments)] pub fn invoke_iiijj( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -675,25 +675,25 @@ pub fn invoke_iiijj( a6 ) } -pub fn invoke_j(mut ctx: ContextMut<'_, EmEnv>, index: i32) -> i32 { +pub fn invoke_j(mut ctx: FunctionEnvMut, index: i32) -> i32 { debug!("emscripten::invoke_j"); invoke_no_stack_save!(ctx, dyn_call_j, dyn_call_j_ref, index) } -pub fn invoke_ji(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32) -> i32 { +pub fn invoke_ji(mut ctx: FunctionEnvMut, index: i32, a1: i32) -> i32 { debug!("emscripten::invoke_ji"); invoke_no_stack_save!(ctx, dyn_call_ji, dyn_call_ji_ref, index, a1) } -pub fn invoke_jii(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) -> i32 { +pub fn invoke_jii(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32) -> i32 { debug!("emscripten::invoke_jii"); invoke_no_stack_save!(ctx, dyn_call_jii, dyn_call_jii_ref, index, a1, a2) } -pub fn invoke_jij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { +pub fn invoke_jij(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32) -> i32 { debug!("emscripten::invoke_jij"); invoke_no_stack_save!(ctx, dyn_call_jij, dyn_call_jij_ref, index, a1, a2, a3) } pub fn invoke_jjj( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -704,7 +704,7 @@ pub fn invoke_jjj( invoke_no_stack_save!(ctx, dyn_call_jjj, dyn_call_jjj_ref, index, a1, a2, a3, a4) } pub fn invoke_viiij( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -727,7 +727,7 @@ pub fn invoke_viiij( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiijiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -758,7 +758,7 @@ pub fn invoke_viiijiiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viiijiiiiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -791,12 +791,12 @@ pub fn invoke_viiijiiiiii( a11 ) } -pub fn invoke_viij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { +pub fn invoke_viij(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { debug!("emscripten::invoke_viij"); invoke_no_stack_save!(ctx, dyn_call_viij, dyn_call_viij_ref, index, a1, a2, a3, a4) } pub fn invoke_viiji( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -819,7 +819,7 @@ pub fn invoke_viiji( } #[allow(clippy::too_many_arguments)] pub fn invoke_viijiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -846,7 +846,7 @@ pub fn invoke_viijiii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viijj( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -869,12 +869,12 @@ pub fn invoke_viijj( a6 ) } -pub fn invoke_vj(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32) { +pub fn invoke_vj(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32) { debug!("emscripten::invoke_vj"); invoke_no_stack_save!(ctx, dyn_call_vj, dyn_call_vj_ref, index, a1, a2) } pub fn invoke_vjji( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -895,17 +895,17 @@ pub fn invoke_vjji( a5 ) } -pub fn invoke_vij(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32) { +pub fn invoke_vij(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32) { debug!("emscripten::invoke_vij"); invoke_no_stack_save!(ctx, dyn_call_vij, dyn_call_vij_ref, index, a1, a2, a3) } -pub fn invoke_viji(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { +pub fn invoke_viji(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: i32, a4: i32) { debug!("emscripten::invoke_viji"); invoke_no_stack_save!(ctx, dyn_call_viji, dyn_call_viji_ref, index, a1, a2, a3, a4) } #[allow(clippy::too_many_arguments)] pub fn invoke_vijiii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -929,7 +929,7 @@ pub fn invoke_vijiii( ) } pub fn invoke_vijj( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -950,16 +950,16 @@ pub fn invoke_vijj( a5 ) } -pub fn invoke_vidd(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: f64, a3: f64) { +pub fn invoke_vidd(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: f64, a3: f64) { debug!("emscripten::invoke_viid"); invoke_no_return!(ctx, dyn_call_vidd, dyn_call_vidd_ref, index, a1, a2, a3); } -pub fn invoke_viid(mut ctx: ContextMut<'_, EmEnv>, index: i32, a1: i32, a2: i32, a3: f64) { +pub fn invoke_viid(mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, a3: f64) { debug!("emscripten::invoke_viid"); invoke_no_return!(ctx, dyn_call_viid, dyn_call_viid_ref, index, a1, a2, a3); } pub fn invoke_viidii( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, @@ -982,7 +982,7 @@ pub fn invoke_viidii( } #[allow(clippy::too_many_arguments)] pub fn invoke_viidddddddd( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, index: i32, a1: i32, a2: i32, diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index fa7c1ab1edc..645f989f3b3 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -19,65 +19,68 @@ use std::sync::MutexGuard; use crate::EmEnv; use wasmer::ValueType; -use wasmer::{AsContextMut, ContextMut, WasmPtr}; +use wasmer::{FunctionEnvMut, WasmPtr}; -pub fn call_malloc(mut ctx: ContextMut<'_, EmEnv>, size: u32) -> u32 { - let malloc_ref = get_emscripten_funcs(&ctx).malloc_ref().unwrap().clone(); - malloc_ref.call(&mut ctx.as_context_mut(), size).unwrap() +pub fn call_malloc(mut ctx: &mut FunctionEnvMut, size: u32) -> u32 { + let malloc_ref = get_emscripten_funcs(ctx).malloc_ref().unwrap().clone(); + malloc_ref.call(&mut ctx, size).unwrap() } #[warn(dead_code)] -pub fn call_malloc_with_cast(ctx: ContextMut<'_, EmEnv>, size: u32) -> WasmPtr { +pub fn call_malloc_with_cast(ctx: &mut FunctionEnvMut, size: u32) -> WasmPtr { WasmPtr::new(call_malloc(ctx, size)) } -pub fn call_memalign(mut ctx: ContextMut<'_, EmEnv>, alignment: u32, size: u32) -> u32 { - let memalign_ref = get_emscripten_funcs(&ctx).memalign_ref().unwrap().clone(); +pub fn call_memalign(mut ctx: &mut FunctionEnvMut, alignment: u32, size: u32) -> u32 { + let memalign_ref = get_emscripten_funcs(ctx).memalign_ref().unwrap().clone(); memalign_ref.call(&mut ctx, alignment, size).unwrap() } -pub fn call_memset(mut ctx: ContextMut<'_, EmEnv>, pointer: u32, value: u32, size: u32) -> u32 { - let memset_ref = get_emscripten_funcs(&ctx).memset_ref().unwrap().clone(); - memset_ref - .call(&mut ctx.as_context_mut(), pointer, value, size) - .unwrap() +pub fn call_memset( + mut ctx: &mut FunctionEnvMut, + pointer: u32, + value: u32, + size: u32, +) -> u32 { + let memset_ref = get_emscripten_funcs(ctx).memset_ref().unwrap().clone(); + memset_ref.call(&mut ctx, pointer, value, size).unwrap() } pub(crate) fn get_emscripten_data<'a>( - ctx: &'a ContextMut<'_, EmEnv>, + ctx: &'a FunctionEnvMut, ) -> MutexGuard<'a, Option> { ctx.data().data.lock().unwrap() } pub(crate) fn get_emscripten_funcs<'a>( - ctx: &'a ContextMut<'_, EmEnv>, + ctx: &'a FunctionEnvMut, ) -> MutexGuard<'a, EmscriptenFunctions> { ctx.data().funcs.lock().unwrap() } -pub fn _getpagesize(_ctx: ContextMut<'_, EmEnv>) -> u32 { +pub fn _getpagesize(_ctx: FunctionEnvMut) -> u32 { debug!("emscripten::_getpagesize"); 16384 } -pub fn _times(ctx: ContextMut<'_, EmEnv>, buffer: u32) -> u32 { +pub fn _times(mut ctx: FunctionEnvMut, buffer: u32) -> u32 { if buffer != 0 { - call_memset(ctx, buffer, 0, 16); + call_memset(&mut ctx, buffer, 0, 16); } 0 } #[allow(clippy::cast_ptr_alignment)] -pub fn ___build_environment(mut ctx: ContextMut<'_, EmEnv>, environ: c_int) { +pub fn ___build_environment(mut ctx: FunctionEnvMut, environ: c_int) { debug!("emscripten::___build_environment {}", environ); const MAX_ENV_VALUES: u32 = 64; const TOTAL_ENV_SIZE: u32 = 1024; let environment = emscripten_memory_pointer!(ctx, ctx.data().memory(0), environ) as *mut c_int; let (mut pool_offset, env_ptr, mut pool_ptr) = unsafe { let (pool_offset, _pool_slice): (u32, &mut [u8]) = - allocate_on_stack(&mut ctx.as_context_mut(), TOTAL_ENV_SIZE as u32); + allocate_on_stack(&mut ctx, TOTAL_ENV_SIZE as u32); let (env_offset, _env_slice): (u32, &mut [u8]) = - allocate_on_stack(&mut ctx.as_context_mut(), (MAX_ENV_VALUES * 4) as u32); + allocate_on_stack(&mut ctx, (MAX_ENV_VALUES * 4) as u32); let env_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), env_offset) as *mut c_int; let pool_ptr = @@ -122,13 +125,13 @@ pub fn ___build_environment(mut ctx: ContextMut<'_, EmEnv>, environ: c_int) { } } -pub fn ___assert_fail(_ctx: ContextMut<'_, EmEnv>, _a: c_int, _b: c_int, _c: c_int, _d: c_int) { +pub fn ___assert_fail(_ctx: FunctionEnvMut, _a: c_int, _b: c_int, _c: c_int, _d: c_int) { debug!("emscripten::___assert_fail {} {} {} {}", _a, _b, _c, _d); // TODO: Implement like emscripten expects regarding memory/page size // TODO raise an error } -pub fn _pathconf(ctx: ContextMut<'_, EmEnv>, path_addr: c_int, name: c_int) -> c_int { +pub fn _pathconf(ctx: FunctionEnvMut, path_addr: c_int, name: c_int) -> c_int { debug!( "emscripten::_pathconf {} {} - UNIMPLEMENTED", path_addr, name @@ -149,7 +152,7 @@ pub fn _pathconf(ctx: ContextMut<'_, EmEnv>, path_addr: c_int, name: c_int) -> c } } -pub fn _fpathconf(_ctx: ContextMut<'_, EmEnv>, _fildes: c_int, name: c_int) -> c_int { +pub fn _fpathconf(_ctx: FunctionEnvMut, _fildes: c_int, name: c_int) -> c_int { debug!("emscripten::_fpathconf {} {}", _fildes, name); match name { 0 => 32000, diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs index 9ef7e59a024..66d6c64434e 100644 --- a/lib/emscripten/src/env/unix/mod.rs +++ b/lib/emscripten/src/env/unix/mod.rs @@ -10,11 +10,11 @@ use std::os::raw::c_char; use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr}; use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs}; use crate::EmEnv; -use wasmer::{AsContextMut, ContextMut, WasmPtr}; +use wasmer::{FunctionEnvMut, WasmPtr}; // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; -pub fn _getenv(ctx: ContextMut<'_, EmEnv>, name: i32) -> u32 { +pub fn _getenv(mut ctx: FunctionEnvMut, name: i32) -> u32 { debug!("emscripten::_getenv"); let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; @@ -26,11 +26,11 @@ pub fn _getenv(ctx: ContextMut<'_, EmEnv>, name: i32) -> u32 { return 0; } - unsafe { copy_cstr_into_wasm(ctx, c_str) } + unsafe { copy_cstr_into_wasm(&mut ctx, c_str) } } /// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int); -pub fn _setenv(ctx: ContextMut<'_, EmEnv>, name: c_int, value: c_int, overwrite: c_int) -> c_int { +pub fn _setenv(ctx: FunctionEnvMut, name: c_int, value: c_int, overwrite: c_int) -> c_int { debug!("emscripten::_setenv"); let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; @@ -43,7 +43,7 @@ pub fn _setenv(ctx: ContextMut<'_, EmEnv>, name: c_int, value: c_int, overwrite: } /// emscripten: _putenv // (name: *const char); -pub fn _putenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { +pub fn _putenv(ctx: FunctionEnvMut, name: c_int) -> c_int { debug!("emscripten::_putenv"); let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; @@ -54,7 +54,7 @@ pub fn _putenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { } /// emscripten: _unsetenv // (name: *const char); -pub fn _unsetenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { +pub fn _unsetenv(ctx: FunctionEnvMut, name: c_int) -> c_int { debug!("emscripten::_unsetenv"); let name_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name) as *const c_char; @@ -65,7 +65,7 @@ pub fn _unsetenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { +pub fn _getpwnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { debug!("emscripten::_getpwnam {}", name_ptr); #[cfg(feature = "debug")] let _ = name_ptr; @@ -89,18 +89,16 @@ pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { unsafe { let passwd = &*libc_getpwnam(name.as_ptr()); - let passwd_struct_offset = - call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); let memory = ctx.data().memory(0); let passwd_struct_ptr = emscripten_memory_pointer!(ctx, memory, passwd_struct_offset) as *mut GuestPasswd; - (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_name); - (*passwd_struct_ptr).pw_passwd = - copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_passwd); - (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_gecos); - (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_dir); - (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_shell); + (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(&mut ctx, passwd.pw_name); + (*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(&mut ctx, passwd.pw_passwd); + (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(&mut ctx, passwd.pw_gecos); + (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(&mut ctx, passwd.pw_dir); + (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(&mut ctx, passwd.pw_shell); (*passwd_struct_ptr).pw_uid = passwd.pw_uid; (*passwd_struct_ptr).pw_gid = passwd.pw_gid; @@ -109,7 +107,7 @@ pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { +pub fn _getgrnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { debug!("emscripten::_getgrnam {}", name_ptr); #[repr(C)] @@ -128,14 +126,13 @@ pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { unsafe { let group = &*libc_getgrnam(name.as_ptr()); - let group_struct_offset = - call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let group_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); let group_struct_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), group_struct_offset) as *mut GuestGroup; - (*group_struct_ptr).gr_name = copy_cstr_into_wasm(ctx.as_context_mut(), group.gr_name); - (*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(ctx.as_context_mut(), group.gr_passwd); + (*group_struct_ptr).gr_name = copy_cstr_into_wasm(&mut ctx, group.gr_name); + (*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(&mut ctx, group.gr_passwd); (*group_struct_ptr).gr_gid = group.gr_gid; (*group_struct_ptr).gr_mem = copy_terminated_array_of_cstrs(ctx, group.gr_mem); @@ -143,20 +140,19 @@ pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { } } -pub fn _sysconf(_ctx: ContextMut<'_, EmEnv>, name: c_int) -> i32 { +pub fn _sysconf(_ctx: FunctionEnvMut, name: c_int) -> i32 { debug!("emscripten::_sysconf {}", name); // TODO: Implement like emscripten expects regarding memory/page size unsafe { sysconf(name) as i32 } // TODO review i64 } // this may be a memory leak, probably not though because emscripten does the same thing -pub fn _gai_strerror(mut ctx: ContextMut<'_, EmEnv>, ecode: i32) -> i32 { +pub fn _gai_strerror(mut ctx: FunctionEnvMut, ecode: i32) -> i32 { debug!("emscripten::_gai_strerror({})", ecode); let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) }; let bytes = cstr.to_bytes_with_nul(); - let string_on_guest: WasmPtr = - call_malloc_with_cast(ctx.as_context_mut(), bytes.len() as _); + let string_on_guest: WasmPtr = call_malloc_with_cast(&mut ctx, bytes.len() as _); let memory = ctx.data().memory(0); let writer = string_on_guest @@ -170,7 +166,7 @@ pub fn _gai_strerror(mut ctx: ContextMut<'_, EmEnv>, ecode: i32) -> i32 { } pub fn _getaddrinfo( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, node_ptr: WasmPtr, service_str_ptr: WasmPtr, hints_ptr: WasmPtr, @@ -244,7 +240,7 @@ pub fn _getaddrinfo( while !current_host_node.is_null() { let current_guest_node_ptr: WasmPtr = - call_malloc_with_cast(ctx.as_context_mut(), std::mem::size_of::() as _); + call_malloc_with_cast(&mut ctx, std::mem::size_of::() as _); if head_of_list.is_none() { head_of_list = Some(current_guest_node_ptr); } @@ -264,7 +260,7 @@ pub fn _getaddrinfo( let guest_sockaddr_ptr = { let host_sockaddr_ptr = (*current_host_node).ai_addr; let guest_sockaddr_ptr: WasmPtr = - call_malloc_with_cast(ctx.as_context_mut(), host_addrlen as _); + call_malloc_with_cast(&mut ctx, host_addrlen as _); let derefed_guest_sockaddr = guest_sockaddr_ptr.deref(&ctx, &memory); let mut gs = derefed_guest_sockaddr.read().unwrap(); @@ -283,7 +279,7 @@ pub fn _getaddrinfo( let canonname_bytes = canonname_cstr.to_bytes_with_nul(); let str_size = canonname_bytes.len(); let guest_canonname: WasmPtr = - call_malloc_with_cast(ctx.as_context_mut(), str_size as _); + call_malloc_with_cast(&mut ctx, str_size as _); let guest_canonname_writer = guest_canonname.slice(&ctx, &memory, str_size as _).unwrap(); diff --git a/lib/emscripten/src/env/windows/mod.rs b/lib/emscripten/src/env/windows/mod.rs index dce90272874..8b35528496c 100644 --- a/lib/emscripten/src/env/windows/mod.rs +++ b/lib/emscripten/src/env/windows/mod.rs @@ -8,7 +8,7 @@ use std::os::raw::c_char; use crate::env::{call_malloc, EmAddrInfo}; use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm}; use crate::EmEnv; -use wasmer::{AsContextMut, ContextMut, WasmPtr}; +use wasmer::{FunctionEnvMut, WasmPtr}; extern "C" { #[link_name = "_putenv"] @@ -17,24 +17,24 @@ extern "C" { // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; -pub fn _getenv(mut ctx: ContextMut<'_, EmEnv>, name: u32) -> u32 { +pub fn _getenv(mut ctx: FunctionEnvMut, name: u32) -> u32 { debug!("emscripten::_getenv"); let memory = ctx.data().memory(0); - let name_string = read_string_from_wasm(ctx.as_context_mut(), &memory, name); + let name_string = read_string_from_wasm(ctx.as_mut(), &memory, name); debug!("=> name({:?})", name_string); let c_str = unsafe { getenv(name_string.as_ptr() as *const libc::c_char) }; if c_str.is_null() { return 0; } - unsafe { copy_cstr_into_wasm(ctx, c_str as *const c_char) } + unsafe { copy_cstr_into_wasm(&mut ctx, c_str as *const c_char) } } /// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int); -pub fn _setenv(mut ctx: ContextMut<'_, EmEnv>, name: u32, value: u32, _overwrite: u32) -> c_int { +pub fn _setenv(mut ctx: FunctionEnvMut, name: u32, value: u32, _overwrite: u32) -> c_int { debug!("emscripten::_setenv"); let memory = ctx.data().memory(0); // setenv does not exist on windows, so we hack it with _putenv - let name = read_string_from_wasm(ctx.as_context_mut(), &memory, name); + let name = read_string_from_wasm(ctx.as_mut(), &memory, name); let value = read_string_from_wasm(ctx, &memory, value); let putenv_string = format!("{}={}", name, value); let putenv_cstring = CString::new(putenv_string).unwrap(); @@ -45,7 +45,7 @@ pub fn _setenv(mut ctx: ContextMut<'_, EmEnv>, name: u32, value: u32, _overwrite } /// emscripten: _putenv // (name: *const char); -pub fn _putenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { +pub fn _putenv(ctx: FunctionEnvMut, name: c_int) -> c_int { debug!("emscripten::_putenv"); let memory = ctx.data().memory(0); let name_addr = emscripten_memory_pointer!(ctx, &memory, name) as *const c_char; @@ -56,7 +56,7 @@ pub fn _putenv(ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_int { } /// emscripten: _unsetenv // (name: *const char); -pub fn _unsetenv(ctx: ContextMut<'_, EmEnv>, name: u32) -> c_int { +pub fn _unsetenv(ctx: FunctionEnvMut, name: u32) -> c_int { debug!("emscripten::_unsetenv"); let memory = ctx.data().memory(0); let name = read_string_from_wasm(ctx, &memory, name); @@ -69,7 +69,7 @@ pub fn _unsetenv(ctx: ContextMut<'_, EmEnv>, name: u32) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { +pub fn _getpwnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { debug!("emscripten::_getpwnam {}", name_ptr); #[cfg(not(feature = "debug"))] let _ = name_ptr; @@ -88,8 +88,7 @@ pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { // stub this in windows as it is not valid unsafe { - let passwd_struct_offset = - call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); let passwd_struct_ptr = emscripten_memory_pointer!(ctx, memory, passwd_struct_offset) as *mut GuestPasswd; (*passwd_struct_ptr).pw_name = 0; @@ -105,7 +104,7 @@ pub fn _getpwnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { +pub fn _getgrnam(mut ctx: FunctionEnvMut, name_ptr: c_int) -> c_int { debug!("emscripten::_getgrnam {}", name_ptr); #[cfg(not(feature = "debug"))] let _ = name_ptr; @@ -121,8 +120,7 @@ pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { // stub the group struct as it is not supported on windows unsafe { - let group_struct_offset = - call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let group_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); let group_struct_ptr = emscripten_memory_pointer!(ctx, memory, group_struct_offset) as *mut GuestGroup; (*group_struct_ptr).gr_name = 0; @@ -133,7 +131,7 @@ pub fn _getgrnam(mut ctx: ContextMut<'_, EmEnv>, name_ptr: c_int) -> c_int { } } -pub fn _sysconf(_ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_long { +pub fn _sysconf(_ctx: FunctionEnvMut, name: c_int) -> c_long { debug!("emscripten::_sysconf {}", name); #[cfg(not(feature = "debug"))] let _ = name; @@ -141,13 +139,13 @@ pub fn _sysconf(_ctx: ContextMut<'_, EmEnv>, name: c_int) -> c_long { 0 } -pub fn _gai_strerror(_ctx: ContextMut<'_, EmEnv>, _ecode: i32) -> i32 { +pub fn _gai_strerror(_ctx: FunctionEnvMut, _ecode: i32) -> i32 { debug!("emscripten::_gai_strerror({}) - stub", _ecode); -1 } pub fn _getaddrinfo( - _ctx: ContextMut<'_, EmEnv>, + _ctx: FunctionEnvMut, _node_ptr: WasmPtr, _service_str_ptr: WasmPtr, _hints_ptr: WasmPtr, diff --git a/lib/emscripten/src/errno.rs b/lib/emscripten/src/errno.rs index fb5681de7c8..99c78bf8c15 100644 --- a/lib/emscripten/src/errno.rs +++ b/lib/emscripten/src/errno.rs @@ -1,8 +1,8 @@ // use std::collections::HashMap; use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; -pub fn ___seterrno(mut _ctx: ContextMut<'_, EmEnv>, _value: i32) { +pub fn ___seterrno(mut _ctx: FunctionEnvMut, _value: i32) { debug!("emscripten::___seterrno {}", _value); // TODO: Incomplete impl eprintln!("failed to set errno!"); diff --git a/lib/emscripten/src/exception.rs b/lib/emscripten/src/exception.rs index c260f1a51d3..c3c8353d4af 100644 --- a/lib/emscripten/src/exception.rs +++ b/lib/emscripten/src/exception.rs @@ -1,57 +1,57 @@ use super::env; use super::process::_abort; use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; /// emscripten: ___cxa_allocate_exception -pub fn ___cxa_allocate_exception(ctx: ContextMut<'_, EmEnv>, size: u32) -> u32 { +pub fn ___cxa_allocate_exception(mut ctx: FunctionEnvMut, size: u32) -> u32 { debug!("emscripten::___cxa_allocate_exception"); - env::call_malloc(ctx, size as _) + env::call_malloc(&mut ctx.as_mut(), size as _) } -pub fn ___cxa_current_primary_exception(_ctx: ContextMut<'_, EmEnv>) -> u32 { +pub fn ___cxa_current_primary_exception(_ctx: FunctionEnvMut) -> u32 { debug!("emscripten::___cxa_current_primary_exception"); unimplemented!("emscripten::___cxa_current_primary_exception") } -pub fn ___cxa_decrement_exception_refcount(_ctx: ContextMut<'_, EmEnv>, _a: u32) { +pub fn ___cxa_decrement_exception_refcount(_ctx: FunctionEnvMut, _a: u32) { debug!("emscripten::___cxa_decrement_exception_refcount({})", _a); unimplemented!("emscripten::___cxa_decrement_exception_refcount({})", _a) } -pub fn ___cxa_increment_exception_refcount(_ctx: ContextMut<'_, EmEnv>, _a: u32) { +pub fn ___cxa_increment_exception_refcount(_ctx: FunctionEnvMut, _a: u32) { debug!("emscripten::___cxa_increment_exception_refcount({})", _a); unimplemented!("emscripten::___cxa_increment_exception_refcount({})", _a) } -pub fn ___cxa_rethrow_primary_exception(_ctx: ContextMut<'_, EmEnv>, _a: u32) { +pub fn ___cxa_rethrow_primary_exception(_ctx: FunctionEnvMut, _a: u32) { debug!("emscripten::___cxa_rethrow_primary_exception({})", _a); unimplemented!("emscripten::___cxa_rethrow_primary_exception({})", _a) } /// emscripten: ___cxa_throw /// TODO: We don't have support for exceptions yet -pub fn ___cxa_throw(ctx: ContextMut<'_, EmEnv>, _ptr: u32, _ty: u32, _destructor: u32) { +pub fn ___cxa_throw(ctx: FunctionEnvMut, _ptr: u32, _ty: u32, _destructor: u32) { debug!("emscripten::___cxa_throw"); eprintln!("Throwing exceptions not yet implemented: aborting!"); _abort(ctx); } -pub fn ___cxa_begin_catch(_ctx: ContextMut<'_, EmEnv>, _exception_object_ptr: u32) -> i32 { +pub fn ___cxa_begin_catch(_ctx: FunctionEnvMut, _exception_object_ptr: u32) -> i32 { debug!("emscripten::___cxa_begin_catch"); -1 } -pub fn ___cxa_end_catch(_ctx: ContextMut<'_, EmEnv>) { +pub fn ___cxa_end_catch(_ctx: FunctionEnvMut) { debug!("emscripten::___cxa_end_catch"); } -pub fn ___cxa_uncaught_exception(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn ___cxa_uncaught_exception(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::___cxa_uncaught_exception"); -1 } -pub fn ___cxa_pure_virtual(_ctx: ContextMut<'_, EmEnv>) { +pub fn ___cxa_pure_virtual(_ctx: FunctionEnvMut) { debug!("emscripten::___cxa_pure_virtual"); // ABORT = true panic!("Pure virtual function called!"); diff --git a/lib/emscripten/src/exec.rs b/lib/emscripten/src/exec.rs index 2b2485a224d..5a159debe3e 100644 --- a/lib/emscripten/src/exec.rs +++ b/lib/emscripten/src/exec.rs @@ -3,9 +3,9 @@ use crate::EmEnv; use libc::c_char; use libc::execvp as libc_execvp; use std::ffi::CString; -use wasmer::{ContextMut, WasmPtr}; +use wasmer::{FunctionEnvMut, WasmPtr}; -pub fn execvp(ctx: ContextMut<'_, EmEnv>, command_name_offset: u32, argv_offset: u32) -> i32 { +pub fn execvp(ctx: FunctionEnvMut, command_name_offset: u32, argv_offset: u32) -> i32 { // a single reference to re-use let emscripten_memory = ctx.data().memory(0); @@ -41,7 +41,7 @@ pub fn execvp(ctx: ContextMut<'_, EmEnv>, command_name_offset: u32, argv_offset: /// execl pub fn execl( - _ctx: ContextMut<'_, EmEnv>, + _ctx: FunctionEnvMut, _path_ptr: i32, _arg0_ptr: i32, _varargs: VarArgs, @@ -52,7 +52,7 @@ pub fn execl( /// execle pub fn execle( - _ctx: ContextMut<'_, EmEnv>, + _ctx: FunctionEnvMut, _path_ptr: i32, _arg0_ptr: i32, _varargs: VarArgs, diff --git a/lib/emscripten/src/exit.rs b/lib/emscripten/src/exit.rs index 8ef28cceb56..907bb66c3cb 100644 --- a/lib/emscripten/src/exit.rs +++ b/lib/emscripten/src/exit.rs @@ -1,8 +1,8 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; // __exit -pub fn exit(mut _ctx: ContextMut<'_, EmEnv>, value: i32) { +pub fn exit(mut _ctx: FunctionEnvMut, value: i32) { debug!("emscripten::exit {}", value); ::std::process::exit(value); } diff --git a/lib/emscripten/src/inet.rs b/lib/emscripten/src/inet.rs index b1a59a0feaf..863a6bc2c8a 100644 --- a/lib/emscripten/src/inet.rs +++ b/lib/emscripten/src/inet.rs @@ -1,7 +1,7 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; -pub fn addr(mut _ctx: ContextMut<'_, EmEnv>, _cp: i32) -> i32 { +pub fn addr(mut _ctx: FunctionEnvMut, _cp: i32) -> i32 { debug!("inet::addr({})", _cp); 0 } diff --git a/lib/emscripten/src/io/mod.rs b/lib/emscripten/src/io/mod.rs index 0971c10d716..7f5db3b27d2 100644 --- a/lib/emscripten/src/io/mod.rs +++ b/lib/emscripten/src/io/mod.rs @@ -11,22 +11,22 @@ pub use self::unix::*; pub use self::windows::*; use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; /// getprotobyname -pub fn getprotobyname(_ctx: ContextMut<'_, EmEnv>, _name_ptr: i32) -> i32 { +pub fn getprotobyname(_ctx: FunctionEnvMut, _name_ptr: i32) -> i32 { debug!("emscripten::getprotobyname"); unimplemented!("emscripten::getprotobyname") } /// getprotobynumber -pub fn getprotobynumber(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn getprotobynumber(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::getprotobynumber"); unimplemented!("emscripten::getprotobynumber") } /// sigdelset -pub fn sigdelset(ctx: ContextMut<'_, EmEnv>, set: i32, signum: i32) -> i32 { +pub fn sigdelset(ctx: FunctionEnvMut, set: i32, signum: i32) -> i32 { debug!("emscripten::sigdelset"); let memory = ctx.data().memory(0); #[allow(clippy::cast_ptr_alignment)] @@ -38,7 +38,7 @@ pub fn sigdelset(ctx: ContextMut<'_, EmEnv>, set: i32, signum: i32) -> i32 { } /// sigfillset -pub fn sigfillset(ctx: ContextMut<'_, EmEnv>, set: i32) -> i32 { +pub fn sigfillset(ctx: FunctionEnvMut, set: i32) -> i32 { debug!("emscripten::sigfillset"); let memory = ctx.data().memory(0); #[allow(clippy::cast_ptr_alignment)] @@ -52,13 +52,13 @@ pub fn sigfillset(ctx: ContextMut<'_, EmEnv>, set: i32) -> i32 { } /// tzset -pub fn tzset(_ctx: ContextMut<'_, EmEnv>) { +pub fn tzset(_ctx: FunctionEnvMut) { debug!("emscripten::tzset - stub"); //unimplemented!("emscripten::tzset - stub") } /// strptime -pub fn strptime(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn strptime(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::strptime"); unimplemented!("emscripten::strptime") } diff --git a/lib/emscripten/src/io/unix.rs b/lib/emscripten/src/io/unix.rs index 0e01580778b..996ebe68e44 100644 --- a/lib/emscripten/src/io/unix.rs +++ b/lib/emscripten/src/io/unix.rs @@ -4,15 +4,15 @@ use libc::{chroot as _chroot, getpwuid as _getpwuid, printf as _printf}; use std::mem; use crate::EmEnv; -use wasmer::{AsContextMut, ContextMut}; +use wasmer::FunctionEnvMut; /// putchar -pub fn putchar(_ctx: ContextMut<'_, EmEnv>, chr: i32) { +pub fn putchar(_ctx: FunctionEnvMut, chr: i32) { unsafe { libc::putchar(chr) }; } /// printf -pub fn printf(ctx: ContextMut<'_, EmEnv>, memory_offset: i32, extra: i32) -> i32 { +pub fn printf(ctx: FunctionEnvMut, memory_offset: i32, extra: i32) -> i32 { debug!("emscripten::printf {}, {}", memory_offset, extra); unsafe { let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), memory_offset) as _; @@ -21,7 +21,7 @@ pub fn printf(ctx: ContextMut<'_, EmEnv>, memory_offset: i32, extra: i32) -> i32 } /// chroot -pub fn chroot(ctx: ContextMut<'_, EmEnv>, name_ptr: i32) -> i32 { +pub fn chroot(ctx: FunctionEnvMut, name_ptr: i32) -> i32 { debug!("emscripten::chroot"); let name = emscripten_memory_pointer!(ctx, ctx.data().memory(0), name_ptr) as *const i8; unsafe { _chroot(name as *const _) } @@ -29,7 +29,7 @@ pub fn chroot(ctx: ContextMut<'_, EmEnv>, name_ptr: i32) -> i32 { /// getpwuid #[allow(clippy::cast_ptr_alignment)] -pub fn getpwuid(mut ctx: ContextMut<'_, EmEnv>, uid: i32) -> i32 { +pub fn getpwuid(mut ctx: FunctionEnvMut, uid: i32) -> i32 { debug!("emscripten::getpwuid {}", uid); #[repr(C)] @@ -45,8 +45,7 @@ pub fn getpwuid(mut ctx: ContextMut<'_, EmEnv>, uid: i32) -> i32 { unsafe { let passwd = &*_getpwuid(uid as _); - let passwd_struct_offset = - call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::() as _); let passwd_struct_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), passwd_struct_offset) as *mut GuestPasswd; @@ -54,12 +53,11 @@ pub fn getpwuid(mut ctx: ContextMut<'_, EmEnv>, uid: i32) -> i32 { passwd_struct_ptr as usize % std::mem::align_of::(), 0 ); - (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_name); - (*passwd_struct_ptr).pw_passwd = - copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_passwd); - (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_gecos); - (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_dir); - (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(ctx.as_context_mut(), passwd.pw_shell); + (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(&mut ctx, passwd.pw_name); + (*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(&mut ctx, passwd.pw_passwd); + (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(&mut ctx, passwd.pw_gecos); + (*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(&mut ctx, passwd.pw_dir); + (*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(&mut ctx, passwd.pw_shell); (*passwd_struct_ptr).pw_uid = passwd.pw_uid; (*passwd_struct_ptr).pw_gid = passwd.pw_gid; diff --git a/lib/emscripten/src/io/windows.rs b/lib/emscripten/src/io/windows.rs index 0bd1d8fbc31..c9b00e575d2 100644 --- a/lib/emscripten/src/io/windows.rs +++ b/lib/emscripten/src/io/windows.rs @@ -1,5 +1,5 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; // This may be problematic for msvc which uses inline functions for the printf family // this cfg_attr will try to link with the legacy lib that does not inline printf @@ -15,12 +15,12 @@ use wasmer::ContextMut; //} /// putchar -pub fn putchar(_ctx: ContextMut<'_, EmEnv>, chr: i32) { +pub fn putchar(_ctx: FunctionEnvMut, chr: i32) { unsafe { libc::putchar(chr) }; } /// printf -pub fn printf(_ctx: ContextMut<'_, EmEnv>, memory_offset: i32, extra: i32) -> i32 { +pub fn printf(_ctx: FunctionEnvMut, memory_offset: i32, extra: i32) -> i32 { debug!("emscripten::printf {}, {}", memory_offset, extra); #[cfg(not(feature = "debug"))] { @@ -35,13 +35,13 @@ pub fn printf(_ctx: ContextMut<'_, EmEnv>, memory_offset: i32, extra: i32) -> i3 } /// chroot -pub fn chroot(_ctx: ContextMut<'_, EmEnv>, _name_ptr: i32) -> i32 { +pub fn chroot(_ctx: FunctionEnvMut, _name_ptr: i32) -> i32 { debug!("emscripten::chroot"); unimplemented!("emscripten::chroot") } /// getpwuid -pub fn getpwuid(_ctx: ContextMut<'_, EmEnv>, _uid: i32) -> i32 { +pub fn getpwuid(_ctx: FunctionEnvMut, _uid: i32) -> i32 { debug!("emscripten::getpwuid"); unimplemented!("emscripten::getpwuid") } diff --git a/lib/emscripten/src/jmp.rs b/lib/emscripten/src/jmp.rs index 9ac824577cc..903a4720787 100644 --- a/lib/emscripten/src/jmp.rs +++ b/lib/emscripten/src/jmp.rs @@ -5,10 +5,10 @@ use libc::c_int; use crate::EmEnv; use std::error::Error; use std::fmt; -use wasmer::{AsContextMut, ContextMut}; +use wasmer::FunctionEnvMut; /// setjmp -pub fn __setjmp(ctx: ContextMut<'_, EmEnv>, _env_addr: u32) -> c_int { +pub fn __setjmp(ctx: FunctionEnvMut, _env_addr: u32) -> c_int { debug!("emscripten::__setjmp (setjmp)"); abort_with_message(ctx, "missing function: _setjmp"); unreachable!() @@ -31,7 +31,7 @@ pub fn __setjmp(ctx: ContextMut<'_, EmEnv>, _env_addr: u32) -> c_int { /// longjmp #[allow(unreachable_code)] -pub fn __longjmp(ctx: ContextMut<'_, EmEnv>, _env_addr: u32, _val: c_int) { +pub fn __longjmp(ctx: FunctionEnvMut, _env_addr: u32, _val: c_int) { debug!("emscripten::__longjmp (longmp)"); abort_with_message(ctx, "missing function: _longjmp"); // unsafe { @@ -59,7 +59,7 @@ impl Error for LongJumpRet {} // This function differs from the js implementation, it should return Result<(), &'static str> #[allow(unreachable_code)] pub fn _longjmp( - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, env_addr: i32, val: c_int, ) -> Result<(), LongJumpRet> { @@ -69,7 +69,7 @@ pub fn _longjmp( .expect("set_threw is None") .clone(); threw - .call(&mut ctx.as_context_mut(), env_addr, val) + .call(&mut ctx, env_addr, val) .expect("set_threw failed to call"); Err(LongJumpRet) } diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 5585e2bcbdc..0ca0884414d 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -23,9 +23,9 @@ use std::f64; use std::path::PathBuf; use std::sync::{Arc, Mutex, RwLock}; use wasmer::{ - imports, namespace, AsContextMut, ContextMut, ExportError, Exports, Function, FunctionType, - Global, Imports, Instance, Memory, MemoryType, Module, Pages, RuntimeError, Table, TableType, - TypedFunction, Value, WasmPtr, + imports, namespace, AsStoreMut, ExportError, Exports, Function, FunctionEnv, FunctionEnvMut, + FunctionType, Global, Imports, Instance, Memory, MemoryType, Module, Pages, RuntimeError, + Table, TableType, TypedFunction, Value, WasmPtr, }; use wasmer_types::Type as ValType; @@ -493,20 +493,20 @@ impl EmscriptenFunctions { /// before calling this function, please initialize `Ctx::data` with a pointer /// to [`EmscriptenData`]. pub fn set_up_emscripten( - ctx: &mut ContextMut<'_, EmEnv>, + store: &mut impl AsStoreMut, instance: &mut Instance, ) -> Result<(), RuntimeError> { // ATINIT // (used by C++) if let Ok(func) = instance.exports.get_function("globalCtors") { - func.call(&mut ctx.as_context_mut(), &[])?; + func.call(store, &[])?; } if let Ok(func) = instance .exports .get_function("___emscripten_environ_constructor") { - func.call(&mut ctx.as_context_mut(), &[])?; + func.call(store, &[])?; } Ok(()) } @@ -548,7 +548,7 @@ pub fn emscripten_get_main_func_name<'a>( pub fn emscripten_call_main( instance: &mut Instance, function_name: &str, - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, path: &str, args: &[&str], ) -> Result<(), RuntimeError> { @@ -561,7 +561,7 @@ pub fn emscripten_call_main( 2 => { let mut new_args = vec![path]; new_args.extend(args); - let (argc, argv) = store_module_arguments(ctx.as_context_mut(), new_args); + let (argc, argv) = store_module_arguments(&mut ctx, new_args); let func: &Function = instance .exports .get(function_name) @@ -592,7 +592,7 @@ pub fn emscripten_call_main( /// Top level function to execute emscripten pub fn run_emscripten_instance( instance: &mut Instance, - mut ctx: ContextMut<'_, EmEnv>, + mut ctx: FunctionEnvMut, globals: &mut EmscriptenGlobals, path: &str, args: Vec<&str>, @@ -817,7 +817,7 @@ pub fn run_emscripten_instance( if let Ok(func) = instance.exports.get_typed_function(&ctx, "stackSave") { emfuncs.stack_save = Some(func); } - if let Ok(func) = instance.exports.get_typed_function(&ctx, "stackRestore") { + if let Ok(func) = instance.exports.get_typed_function(&ctx, "stackRe&mut ctx") { emfuncs.stack_restore = Some(func); } if let Ok(func) = instance.exports.get_typed_function(&ctx, "setThrew") { @@ -825,7 +825,7 @@ pub fn run_emscripten_instance( } ctx.data_mut().set_functions(emfuncs); - set_up_emscripten(&mut ctx.as_context_mut(), instance)?; + set_up_emscripten(&mut ctx, instance)?; let main_func_names = ["_main", "main"]; if let Some(ep) = entrypoint.as_ref() { @@ -844,16 +844,16 @@ pub fn run_emscripten_instance( Ok(()) } -fn store_module_arguments(mut ctx: ContextMut<'_, EmEnv>, args: Vec<&str>) -> (u32, u32) { +fn store_module_arguments(ctx: &mut FunctionEnvMut, args: Vec<&str>) -> (u32, u32) { let argc = args.len() + 1; let mut args_slice = vec![0; argc]; for (slot, arg) in args_slice[0..argc].iter_mut().zip(args.iter()) { - *slot = unsafe { allocate_cstr_on_stack(&mut ctx.as_context_mut(), arg).0 }; + *slot = unsafe { allocate_cstr_on_stack(&mut ctx.as_mut(), arg).0 }; } let (argv_offset, argv_slice): (_, &mut [u32]) = - unsafe { allocate_on_stack(&mut ctx, ((argc) * 4) as u32) }; + unsafe { allocate_on_stack(&mut ctx.as_mut(), ((argc) * 4) as u32) }; assert!(!argv_slice.is_empty()); for (slot, arg) in argv_slice[0..argc].iter_mut().zip(args_slice.iter()) { *slot = *arg @@ -864,15 +864,16 @@ fn store_module_arguments(mut ctx: ContextMut<'_, EmEnv>, args: Vec<&str>) -> (u } pub fn emscripten_set_up_memory( - mut ctx: ContextMut<'_, EmEnv>, + store: &mut impl AsStoreMut, + ctx: &FunctionEnv, memory: &Memory, globals: &EmscriptenGlobalsData, ) -> Result<(), String> { - ctx.data_mut().set_memory(memory.clone()); - let dynamictop_ptr = WasmPtr::::new(globals.dynamictop_ptr).deref(&ctx, memory); + ctx.as_mut(store).set_memory(memory.clone()); + let dynamictop_ptr = WasmPtr::::new(globals.dynamictop_ptr).deref(store, memory); let dynamic_base = globals.dynamic_base; - if dynamictop_ptr.offset() >= memory.data_size(&ctx) { + if dynamictop_ptr.offset() >= memory.data_size(store) { return Err("dynamictop_ptr beyond memory len".to_string()); } dynamictop_ptr.write(dynamic_base as i32).unwrap(); @@ -906,7 +907,8 @@ pub struct EmscriptenGlobals { impl EmscriptenGlobals { pub fn new( - mut ctx: ContextMut<'_, EmEnv>, + mut store: &mut impl AsStoreMut, + ctx: &FunctionEnv, module: &Module, /*, static_bump: u32 */ ) -> Result { let mut use_old_abort_on_cannot_grow_memory = false; @@ -924,14 +926,14 @@ impl EmscriptenGlobals { // Memory initialization let memory_type = MemoryType::new(memory_min, memory_max, shared); - let memory = Memory::new(&mut ctx, memory_type).unwrap(); + let memory = Memory::new(&mut store, memory_type).unwrap(); let table_type = TableType { ty: ValType::FuncRef, minimum: table_min, maximum: table_max, }; - let table = Table::new(&mut ctx, table_type, Value::FuncRef(None)).unwrap(); + let table = Table::new(&mut store, table_type, Value::FuncRef(None)).unwrap(); let data = { let static_bump = STATIC_BUMP; @@ -969,7 +971,7 @@ impl EmscriptenGlobals { } }; - emscripten_set_up_memory(ctx, &memory, &data)?; + emscripten_set_up_memory(store, ctx, &memory, &data)?; let mut null_function_names = vec![]; for import in module.imports().functions() { @@ -993,13 +995,18 @@ impl EmscriptenGlobals { } pub fn generate_emscripten_env( - ctx: &mut ContextMut<'_, EmEnv>, + mut store: &mut impl AsStoreMut, + ctx: &FunctionEnv, globals: &mut EmscriptenGlobals, ) -> Imports { let abort_on_cannot_grow_memory_export = if globals.data.use_old_abort_on_cannot_grow_memory { - Function::new_native(ctx, crate::memory::abort_on_cannot_grow_memory_old) + Function::new_native( + &mut store, + ctx, + crate::memory::abort_on_cannot_grow_memory_old, + ) } else { - Function::new_native(ctx, crate::memory::abort_on_cannot_grow_memory) + Function::new_native(&mut store, ctx, crate::memory::abort_on_cannot_grow_memory) }; let mut env_ns: Exports = namespace! { @@ -1007,440 +1014,440 @@ pub fn generate_emscripten_env( "table" => globals.table.clone(), // Globals - "STACKTOP" => Global::new(ctx, Value::I32(globals.data.stacktop as i32)), - "STACK_MAX" => Global::new(ctx, Value::I32(globals.data.stack_max as i32)), - "DYNAMICTOP_PTR" => Global::new(ctx, Value::I32(globals.data.dynamictop_ptr as i32)), - "fb" => Global::new(ctx, Value::I32(globals.data.table_base as i32)), - "tableBase" => Global::new(ctx, Value::I32(globals.data.table_base as i32)), - "__table_base" => Global::new(ctx, Value::I32(globals.data.table_base as i32)), - "ABORT" => Global::new(ctx, Value::I32(globals.data.abort as i32)), - "gb" => Global::new(ctx, Value::I32(globals.data.memory_base as i32)), - "memoryBase" => Global::new(ctx, Value::I32(globals.data.memory_base as i32)), - "__memory_base" => Global::new(ctx, Value::I32(globals.data.memory_base as i32)), - "tempDoublePtr" => Global::new(ctx, Value::I32(globals.data.temp_double_ptr as i32)), + "STACKTOP" => Global::new(&mut store, Value::I32(globals.data.stacktop as i32)), + "STACK_MAX" => Global::new(&mut store, Value::I32(globals.data.stack_max as i32)), + "DYNAMICTOP_PTR" => Global::new(&mut store, Value::I32(globals.data.dynamictop_ptr as i32)), + "fb" => Global::new(&mut store, Value::I32(globals.data.table_base as i32)), + "tableBase" => Global::new(&mut store, Value::I32(globals.data.table_base as i32)), + "__table_base" => Global::new(&mut store, Value::I32(globals.data.table_base as i32)), + "ABORT" => Global::new(&mut store, Value::I32(globals.data.abort as i32)), + "gb" => Global::new(&mut store, Value::I32(globals.data.memory_base as i32)), + "memoryBase" => Global::new(&mut store, Value::I32(globals.data.memory_base as i32)), + "__memory_base" => Global::new(&mut store, Value::I32(globals.data.memory_base as i32)), + "tempDoublePtr" => Global::new(&mut store, Value::I32(globals.data.temp_double_ptr as i32)), // inet - "_inet_addr" => Function::new_native(ctx, crate::inet::addr), + "_inet_addr" => Function::new_native(&mut store, ctx, crate::inet::addr), // IO - "printf" => Function::new_native(ctx, crate::io::printf), - "putchar" => Function::new_native(ctx, crate::io::putchar), - "___lock" => Function::new_native(ctx, crate::lock::___lock), - "___unlock" => Function::new_native(ctx, crate::lock::___unlock), - "___wait" => Function::new_native(ctx, crate::lock::___wait), - "_flock" => Function::new_native(ctx, crate::lock::_flock), - "_chroot" => Function::new_native(ctx, crate::io::chroot), - "_getprotobyname" => Function::new_native(ctx, crate::io::getprotobyname), - "_getprotobynumber" => Function::new_native(ctx, crate::io::getprotobynumber), - "_getpwuid" => Function::new_native(ctx, crate::io::getpwuid), - "_sigdelset" => Function::new_native(ctx, crate::io::sigdelset), - "_sigfillset" => Function::new_native(ctx, crate::io::sigfillset), - "_tzset" => Function::new_native(ctx, crate::io::tzset), - "_strptime" => Function::new_native(ctx, crate::io::strptime), + "printf" => Function::new_native(&mut store, ctx, crate::io::printf), + "putchar" => Function::new_native(&mut store, ctx, crate::io::putchar), + "___lock" => Function::new_native(&mut store, ctx, crate::lock::___lock), + "___unlock" => Function::new_native(&mut store, ctx, crate::lock::___unlock), + "___wait" => Function::new_native(&mut store, ctx, crate::lock::___wait), + "_flock" => Function::new_native(&mut store, ctx, crate::lock::_flock), + "_chroot" => Function::new_native(&mut store, ctx, crate::io::chroot), + "_getprotobyname" => Function::new_native(&mut store, ctx, crate::io::getprotobyname), + "_getprotobynumber" => Function::new_native(&mut store, ctx, crate::io::getprotobynumber), + "_getpwuid" => Function::new_native(&mut store, ctx, crate::io::getpwuid), + "_sigdelset" => Function::new_native(&mut store, ctx, crate::io::sigdelset), + "_sigfillset" => Function::new_native(&mut store, ctx, crate::io::sigfillset), + "_tzset" => Function::new_native(&mut store, ctx, crate::io::tzset), + "_strptime" => Function::new_native(&mut store, ctx, crate::io::strptime), // exec - "_execvp" => Function::new_native(ctx, crate::exec::execvp), - "_execl" => Function::new_native(ctx, crate::exec::execl), - "_execle" => Function::new_native(ctx, crate::exec::execle), + "_execvp" => Function::new_native(&mut store, ctx, crate::exec::execvp), + "_execl" => Function::new_native(&mut store, ctx, crate::exec::execl), + "_execle" => Function::new_native(&mut store, ctx, crate::exec::execle), // exit - "__exit" => Function::new_native(ctx, crate::exit::exit), + "__exit" => Function::new_native(&mut store, ctx, crate::exit::exit), // Env - "___assert_fail" => Function::new_native(ctx, crate::env::___assert_fail), - "_getenv" => Function::new_native(ctx, crate::env::_getenv), - "_setenv" => Function::new_native(ctx, crate::env::_setenv), - "_putenv" => Function::new_native(ctx, crate::env::_putenv), - "_unsetenv" => Function::new_native(ctx, crate::env::_unsetenv), - "_getpwnam" => Function::new_native(ctx, crate::env::_getpwnam), - "_getgrnam" => Function::new_native(ctx, crate::env::_getgrnam), - "___buildEnvironment" => Function::new_native(ctx, crate::env::___build_environment), - "___setErrNo" => Function::new_native(ctx, crate::errno::___seterrno), - "_getpagesize" => Function::new_native(ctx, crate::env::_getpagesize), - "_sysconf" => Function::new_native(ctx, crate::env::_sysconf), - "_getaddrinfo" => Function::new_native(ctx, crate::env::_getaddrinfo), - "_times" => Function::new_native(ctx, crate::env::_times), - "_pathconf" => Function::new_native(ctx, crate::env::_pathconf), - "_fpathconf" => Function::new_native(ctx, crate::env::_fpathconf), + "___assert_fail" => Function::new_native(&mut store, ctx, crate::env::___assert_fail), + "_getenv" => Function::new_native(&mut store, ctx, crate::env::_getenv), + "_setenv" => Function::new_native(&mut store, ctx, crate::env::_setenv), + "_putenv" => Function::new_native(&mut store, ctx, crate::env::_putenv), + "_unsetenv" => Function::new_native(&mut store, ctx, crate::env::_unsetenv), + "_getpwnam" => Function::new_native(&mut store, ctx, crate::env::_getpwnam), + "_getgrnam" => Function::new_native(&mut store, ctx, crate::env::_getgrnam), + "___buildEnvironment" => Function::new_native(&mut store, ctx, crate::env::___build_environment), + "___setErrNo" => Function::new_native(&mut store, ctx, crate::errno::___seterrno), + "_getpagesize" => Function::new_native(&mut store, ctx, crate::env::_getpagesize), + "_sysconf" => Function::new_native(&mut store, ctx, crate::env::_sysconf), + "_getaddrinfo" => Function::new_native(&mut store, ctx, crate::env::_getaddrinfo), + "_times" => Function::new_native(&mut store, ctx, crate::env::_times), + "_pathconf" => Function::new_native(&mut store, ctx, crate::env::_pathconf), + "_fpathconf" => Function::new_native(&mut store, ctx, crate::env::_fpathconf), // Syscalls - "___syscall1" => Function::new_native(ctx, crate::syscalls::___syscall1), - "___syscall3" => Function::new_native(ctx, crate::syscalls::___syscall3), - "___syscall4" => Function::new_native(ctx, crate::syscalls::___syscall4), - "___syscall5" => Function::new_native(ctx, crate::syscalls::___syscall5), - "___syscall6" => Function::new_native(ctx, crate::syscalls::___syscall6), - "___syscall9" => Function::new_native(ctx, crate::syscalls::___syscall9), - "___syscall10" => Function::new_native(ctx, crate::syscalls::___syscall10), - "___syscall12" => Function::new_native(ctx, crate::syscalls::___syscall12), - "___syscall14" => Function::new_native(ctx, crate::syscalls::___syscall14), - "___syscall15" => Function::new_native(ctx, crate::syscalls::___syscall15), - "___syscall20" => Function::new_native(ctx, crate::syscalls::___syscall20), - "___syscall21" => Function::new_native(ctx, crate::syscalls::___syscall21), - "___syscall25" => Function::new_native(ctx, crate::syscalls::___syscall25), - "___syscall29" => Function::new_native(ctx, crate::syscalls::___syscall29), - "___syscall32" => Function::new_native(ctx, crate::syscalls::___syscall32), - "___syscall33" => Function::new_native(ctx, crate::syscalls::___syscall33), - "___syscall34" => Function::new_native(ctx, crate::syscalls::___syscall34), - "___syscall36" => Function::new_native(ctx, crate::syscalls::___syscall36), - "___syscall39" => Function::new_native(ctx, crate::syscalls::___syscall39), - "___syscall38" => Function::new_native(ctx, crate::syscalls::___syscall38), - "___syscall40" => Function::new_native(ctx, crate::syscalls::___syscall40), - "___syscall41" => Function::new_native(ctx, crate::syscalls::___syscall41), - "___syscall42" => Function::new_native(ctx, crate::syscalls::___syscall42), - "___syscall51" => Function::new_native(ctx, crate::syscalls::___syscall51), - "___syscall52" => Function::new_native(ctx, crate::syscalls::___syscall52), - "___syscall53" => Function::new_native(ctx, crate::syscalls::___syscall53), - "___syscall54" => Function::new_native(ctx, crate::syscalls::___syscall54), - "___syscall57" => Function::new_native(ctx, crate::syscalls::___syscall57), - "___syscall60" => Function::new_native(ctx, crate::syscalls::___syscall60), - "___syscall63" => Function::new_native(ctx, crate::syscalls::___syscall63), - "___syscall64" => Function::new_native(ctx, crate::syscalls::___syscall64), - "___syscall66" => Function::new_native(ctx, crate::syscalls::___syscall66), - "___syscall75" => Function::new_native(ctx, crate::syscalls::___syscall75), - "___syscall77" => Function::new_native(ctx, crate::syscalls::___syscall77), - "___syscall83" => Function::new_native(ctx, crate::syscalls::___syscall83), - "___syscall85" => Function::new_native(ctx, crate::syscalls::___syscall85), - "___syscall91" => Function::new_native(ctx, crate::syscalls::___syscall91), - "___syscall94" => Function::new_native(ctx, crate::syscalls::___syscall94), - "___syscall96" => Function::new_native(ctx, crate::syscalls::___syscall96), - "___syscall97" => Function::new_native(ctx, crate::syscalls::___syscall97), - "___syscall102" => Function::new_native(ctx, crate::syscalls::___syscall102), - "___syscall110" => Function::new_native(ctx, crate::syscalls::___syscall110), - "___syscall114" => Function::new_native(ctx, crate::syscalls::___syscall114), - "___syscall118" => Function::new_native(ctx, crate::syscalls::___syscall118), - "___syscall121" => Function::new_native(ctx, crate::syscalls::___syscall121), - "___syscall122" => Function::new_native(ctx, crate::syscalls::___syscall122), - "___syscall125" => Function::new_native(ctx, crate::syscalls::___syscall125), - "___syscall132" => Function::new_native(ctx, crate::syscalls::___syscall132), - "___syscall133" => Function::new_native(ctx, crate::syscalls::___syscall133), - "___syscall140" => Function::new_native(ctx, crate::syscalls::___syscall140), - "___syscall142" => Function::new_native(ctx, crate::syscalls::___syscall142), - "___syscall144" => Function::new_native(ctx, crate::syscalls::___syscall144), - "___syscall145" => Function::new_native(ctx, crate::syscalls::___syscall145), - "___syscall146" => Function::new_native(ctx, crate::syscalls::___syscall146), - "___syscall147" => Function::new_native(ctx, crate::syscalls::___syscall147), - "___syscall148" => Function::new_native(ctx, crate::syscalls::___syscall148), - "___syscall150" => Function::new_native(ctx, crate::syscalls::___syscall150), - "___syscall151" => Function::new_native(ctx, crate::syscalls::___syscall151), - "___syscall152" => Function::new_native(ctx, crate::syscalls::___syscall152), - "___syscall153" => Function::new_native(ctx, crate::syscalls::___syscall153), - "___syscall163" => Function::new_native(ctx, crate::syscalls::___syscall163), - "___syscall168" => Function::new_native(ctx, crate::syscalls::___syscall168), - "___syscall180" => Function::new_native(ctx, crate::syscalls::___syscall180), - "___syscall181" => Function::new_native(ctx, crate::syscalls::___syscall181), - "___syscall183" => Function::new_native(ctx, crate::syscalls::___syscall183), - "___syscall191" => Function::new_native(ctx, crate::syscalls::___syscall191), - "___syscall192" => Function::new_native(ctx, crate::syscalls::___syscall192), - "___syscall193" => Function::new_native(ctx, crate::syscalls::___syscall193), - "___syscall194" => Function::new_native(ctx, crate::syscalls::___syscall194), - "___syscall195" => Function::new_native(ctx, crate::syscalls::___syscall195), - "___syscall196" => Function::new_native(ctx, crate::syscalls::___syscall196), - "___syscall197" => Function::new_native(ctx, crate::syscalls::___syscall197), - "___syscall198" => Function::new_native(ctx, crate::syscalls::___syscall198), - "___syscall199" => Function::new_native(ctx, crate::syscalls::___syscall199), - "___syscall200" => Function::new_native(ctx, crate::syscalls::___syscall200), - "___syscall201" => Function::new_native(ctx, crate::syscalls::___syscall201), - "___syscall202" => Function::new_native(ctx, crate::syscalls::___syscall202), - "___syscall205" => Function::new_native(ctx, crate::syscalls::___syscall205), - "___syscall207" => Function::new_native(ctx, crate::syscalls::___syscall207), - "___syscall209" => Function::new_native(ctx, crate::syscalls::___syscall209), - "___syscall211" => Function::new_native(ctx, crate::syscalls::___syscall211), - "___syscall212" => Function::new_native(ctx, crate::syscalls::___syscall212), - "___syscall218" => Function::new_native(ctx, crate::syscalls::___syscall218), - "___syscall219" => Function::new_native(ctx, crate::syscalls::___syscall219), - "___syscall220" => Function::new_native(ctx, crate::syscalls::___syscall220), - "___syscall221" => Function::new_native(ctx, crate::syscalls::___syscall221), - "___syscall268" => Function::new_native(ctx, crate::syscalls::___syscall268), - "___syscall269" => Function::new_native(ctx, crate::syscalls::___syscall269), - "___syscall272" => Function::new_native(ctx, crate::syscalls::___syscall272), - "___syscall295" => Function::new_native(ctx, crate::syscalls::___syscall295), - "___syscall296" => Function::new_native(ctx, crate::syscalls::___syscall296), - "___syscall297" => Function::new_native(ctx, crate::syscalls::___syscall297), - "___syscall298" => Function::new_native(ctx, crate::syscalls::___syscall298), - "___syscall300" => Function::new_native(ctx, crate::syscalls::___syscall300), - "___syscall301" => Function::new_native(ctx, crate::syscalls::___syscall301), - "___syscall302" => Function::new_native(ctx, crate::syscalls::___syscall302), - "___syscall303" => Function::new_native(ctx, crate::syscalls::___syscall303), - "___syscall304" => Function::new_native(ctx, crate::syscalls::___syscall304), - "___syscall305" => Function::new_native(ctx, crate::syscalls::___syscall305), - "___syscall306" => Function::new_native(ctx, crate::syscalls::___syscall306), - "___syscall307" => Function::new_native(ctx, crate::syscalls::___syscall307), - "___syscall308" => Function::new_native(ctx, crate::syscalls::___syscall308), - "___syscall320" => Function::new_native(ctx, crate::syscalls::___syscall320), - "___syscall324" => Function::new_native(ctx, crate::syscalls::___syscall324), - "___syscall330" => Function::new_native(ctx, crate::syscalls::___syscall330), - "___syscall331" => Function::new_native(ctx, crate::syscalls::___syscall331), - "___syscall333" => Function::new_native(ctx, crate::syscalls::___syscall333), - "___syscall334" => Function::new_native(ctx, crate::syscalls::___syscall334), - "___syscall337" => Function::new_native(ctx, crate::syscalls::___syscall337), - "___syscall340" => Function::new_native(ctx, crate::syscalls::___syscall340), - "___syscall345" => Function::new_native(ctx, crate::syscalls::___syscall345), + "___syscall1" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall1), + "___syscall3" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall3), + "___syscall4" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall4), + "___syscall5" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall5), + "___syscall6" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall6), + "___syscall9" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall9), + "___syscall10" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall10), + "___syscall12" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall12), + "___syscall14" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall14), + "___syscall15" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall15), + "___syscall20" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall20), + "___syscall21" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall21), + "___syscall25" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall25), + "___syscall29" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall29), + "___syscall32" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall32), + "___syscall33" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall33), + "___syscall34" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall34), + "___syscall36" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall36), + "___syscall39" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall39), + "___syscall38" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall38), + "___syscall40" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall40), + "___syscall41" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall41), + "___syscall42" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall42), + "___syscall51" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall51), + "___syscall52" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall52), + "___syscall53" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall53), + "___syscall54" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall54), + "___syscall57" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall57), + "___syscall60" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall60), + "___syscall63" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall63), + "___syscall64" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall64), + "___syscall66" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall66), + "___syscall75" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall75), + "___syscall77" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall77), + "___syscall83" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall83), + "___syscall85" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall85), + "___syscall91" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall91), + "___syscall94" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall94), + "___syscall96" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall96), + "___syscall97" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall97), + "___syscall102" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall102), + "___syscall110" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall110), + "___syscall114" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall114), + "___syscall118" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall118), + "___syscall121" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall121), + "___syscall122" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall122), + "___syscall125" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall125), + "___syscall132" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall132), + "___syscall133" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall133), + "___syscall140" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall140), + "___syscall142" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall142), + "___syscall144" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall144), + "___syscall145" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall145), + "___syscall146" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall146), + "___syscall147" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall147), + "___syscall148" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall148), + "___syscall150" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall150), + "___syscall151" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall151), + "___syscall152" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall152), + "___syscall153" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall153), + "___syscall163" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall163), + "___syscall168" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall168), + "___syscall180" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall180), + "___syscall181" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall181), + "___syscall183" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall183), + "___syscall191" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall191), + "___syscall192" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall192), + "___syscall193" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall193), + "___syscall194" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall194), + "___syscall195" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall195), + "___syscall196" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall196), + "___syscall197" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall197), + "___syscall198" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall198), + "___syscall199" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall199), + "___syscall200" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall200), + "___syscall201" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall201), + "___syscall202" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall202), + "___syscall205" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall205), + "___syscall207" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall207), + "___syscall209" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall209), + "___syscall211" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall211), + "___syscall212" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall212), + "___syscall218" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall218), + "___syscall219" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall219), + "___syscall220" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall220), + "___syscall221" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall221), + "___syscall268" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall268), + "___syscall269" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall269), + "___syscall272" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall272), + "___syscall295" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall295), + "___syscall296" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall296), + "___syscall297" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall297), + "___syscall298" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall298), + "___syscall300" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall300), + "___syscall301" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall301), + "___syscall302" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall302), + "___syscall303" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall303), + "___syscall304" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall304), + "___syscall305" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall305), + "___syscall306" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall306), + "___syscall307" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall307), + "___syscall308" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall308), + "___syscall320" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall320), + "___syscall324" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall324), + "___syscall330" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall330), + "___syscall331" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall331), + "___syscall333" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall333), + "___syscall334" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall334), + "___syscall337" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall337), + "___syscall340" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall340), + "___syscall345" => Function::new_native(&mut store, ctx, crate::syscalls::___syscall345), // Process - "abort" => Function::new_native(ctx, crate::process::em_abort), - "_abort" => Function::new_native(ctx, crate::process::_abort), - "_prctl" => Function::new_native(ctx, crate::process::_prctl), - "abortStackOverflow" => Function::new_native(ctx, crate::process::abort_stack_overflow), - "_llvm_trap" => Function::new_native(ctx, crate::process::_llvm_trap), - "_fork" => Function::new_native(ctx, crate::process::_fork), - "_exit" => Function::new_native(ctx, crate::process::_exit), - "_system" => Function::new_native(ctx, crate::process::_system), - "_popen" => Function::new_native(ctx, crate::process::_popen), - "_endgrent" => Function::new_native(ctx, crate::process::_endgrent), - "_execve" => Function::new_native(ctx, crate::process::_execve), - "_kill" => Function::new_native(ctx, crate::process::_kill), - "_llvm_stackrestore" => Function::new_native(ctx, crate::process::_llvm_stackrestore), - "_llvm_stacksave" => Function::new_native(ctx, crate::process::_llvm_stacksave), - "_llvm_eh_typeid_for" => Function::new_native(ctx, crate::process::_llvm_eh_typeid_for), - "_raise" => Function::new_native(ctx, crate::process::_raise), - "_sem_init" => Function::new_native(ctx, crate::process::_sem_init), - "_sem_destroy" => Function::new_native(ctx, crate::process::_sem_destroy), - "_sem_post" => Function::new_native(ctx, crate::process::_sem_post), - "_sem_wait" => Function::new_native(ctx, crate::process::_sem_wait), - "_getgrent" => Function::new_native(ctx, crate::process::_getgrent), - "_sched_yield" => Function::new_native(ctx, crate::process::_sched_yield), - "_setgrent" => Function::new_native(ctx, crate::process::_setgrent), - "_setgroups" => Function::new_native(ctx, crate::process::_setgroups), - "_setitimer" => Function::new_native(ctx, crate::process::_setitimer), - "_usleep" => Function::new_native(ctx, crate::process::_usleep), - "_nanosleep" => Function::new_native(ctx, crate::process::_nanosleep), - "_utime" => Function::new_native(ctx, crate::process::_utime), - "_utimes" => Function::new_native(ctx, crate::process::_utimes), - "_wait" => Function::new_native(ctx, crate::process::_wait), - "_wait3" => Function::new_native(ctx, crate::process::_wait3), - "_wait4" => Function::new_native(ctx, crate::process::_wait4), - "_waitid" => Function::new_native(ctx, crate::process::_waitid), - "_waitpid" => Function::new_native(ctx, crate::process::_waitpid), + "abort" => Function::new_native(&mut store, ctx, crate::process::em_abort), + "_abort" => Function::new_native(&mut store, ctx, crate::process::_abort), + "_prctl" => Function::new_native(&mut store, ctx, crate::process::_prctl), + "abortStackOverflow" => Function::new_native(&mut store, ctx, crate::process::abort_stack_overflow), + "_llvm_trap" => Function::new_native(&mut store, ctx, crate::process::_llvm_trap), + "_fork" => Function::new_native(&mut store, ctx, crate::process::_fork), + "_exit" => Function::new_native(&mut store, ctx, crate::process::_exit), + "_system" => Function::new_native(&mut store, ctx, crate::process::_system), + "_popen" => Function::new_native(&mut store, ctx, crate::process::_popen), + "_endgrent" => Function::new_native(&mut store, ctx, crate::process::_endgrent), + "_execve" => Function::new_native(&mut store, ctx, crate::process::_execve), + "_kill" => Function::new_native(&mut store, ctx, crate::process::_kill), + "_llvm_stackrestore" => Function::new_native(&mut store, ctx, crate::process::_llvm_stackrestore), + "_llvm_stacksave" => Function::new_native(&mut store, ctx, crate::process::_llvm_stacksave), + "_llvm_eh_typeid_for" => Function::new_native(&mut store, ctx, crate::process::_llvm_eh_typeid_for), + "_raise" => Function::new_native(&mut store, ctx, crate::process::_raise), + "_sem_init" => Function::new_native(&mut store, ctx, crate::process::_sem_init), + "_sem_destroy" => Function::new_native(&mut store, ctx, crate::process::_sem_destroy), + "_sem_post" => Function::new_native(&mut store, ctx, crate::process::_sem_post), + "_sem_wait" => Function::new_native(&mut store, ctx, crate::process::_sem_wait), + "_getgrent" => Function::new_native(&mut store, ctx, crate::process::_getgrent), + "_sched_yield" => Function::new_native(&mut store, ctx, crate::process::_sched_yield), + "_setgrent" => Function::new_native(&mut store, ctx, crate::process::_setgrent), + "_setgroups" => Function::new_native(&mut store, ctx, crate::process::_setgroups), + "_setitimer" => Function::new_native(&mut store, ctx, crate::process::_setitimer), + "_usleep" => Function::new_native(&mut store, ctx, crate::process::_usleep), + "_nanosleep" => Function::new_native(&mut store, ctx, crate::process::_nanosleep), + "_utime" => Function::new_native(&mut store, ctx, crate::process::_utime), + "_utimes" => Function::new_native(&mut store, ctx, crate::process::_utimes), + "_wait" => Function::new_native(&mut store, ctx, crate::process::_wait), + "_wait3" => Function::new_native(&mut store, ctx, crate::process::_wait3), + "_wait4" => Function::new_native(&mut store, ctx, crate::process::_wait4), + "_waitid" => Function::new_native(&mut store, ctx, crate::process::_waitid), + "_waitpid" => Function::new_native(&mut store, ctx, crate::process::_waitpid), // Emscripten - "_emscripten_asm_const_i" => Function::new_native(ctx, crate::emscripten_target::asm_const_i), - "_emscripten_exit_with_live_runtime" => Function::new_native(ctx, crate::emscripten_target::exit_with_live_runtime), + "_emscripten_asm_const_i" => Function::new_native(&mut store, ctx, crate::emscripten_target::asm_const_i), + "_emscripten_exit_with_live_runtime" => Function::new_native(&mut store, ctx, crate::emscripten_target::exit_with_live_runtime), // Signal - "_sigemptyset" => Function::new_native(ctx, crate::signal::_sigemptyset), - "_sigaddset" => Function::new_native(ctx, crate::signal::_sigaddset), - "_sigprocmask" => Function::new_native(ctx, crate::signal::_sigprocmask), - "_sigaction" => Function::new_native(ctx, crate::signal::_sigaction), - "_signal" => Function::new_native(ctx, crate::signal::_signal), - "_sigsuspend" => Function::new_native(ctx, crate::signal::_sigsuspend), + "_sigemptyset" => Function::new_native(&mut store, ctx, crate::signal::_sigemptyset), + "_sigaddset" => Function::new_native(&mut store, ctx, crate::signal::_sigaddset), + "_sigprocmask" => Function::new_native(&mut store, ctx, crate::signal::_sigprocmask), + "_sigaction" => Function::new_native(&mut store, ctx, crate::signal::_sigaction), + "_signal" => Function::new_native(&mut store, ctx, crate::signal::_signal), + "_sigsuspend" => Function::new_native(&mut store, ctx, crate::signal::_sigsuspend), // Memory "abortOnCannotGrowMemory" => abort_on_cannot_grow_memory_export, - "_emscripten_memcpy_big" => Function::new_native(ctx, crate::memory::_emscripten_memcpy_big), - "_emscripten_get_heap_size" => Function::new_native(ctx, crate::memory::_emscripten_get_heap_size), - "_emscripten_resize_heap" => Function::new_native(ctx, crate::memory::_emscripten_resize_heap), - "enlargeMemory" => Function::new_native(ctx, crate::memory::enlarge_memory), - "segfault" => Function::new_native(ctx, crate::memory::segfault), - "alignfault" => Function::new_native(ctx, crate::memory::alignfault), - "ftfault" => Function::new_native(ctx, crate::memory::ftfault), - "getTotalMemory" => Function::new_native(ctx, crate::memory::get_total_memory), - "_sbrk" => Function::new_native(ctx, crate::memory::sbrk), - "___map_file" => Function::new_native(ctx, crate::memory::___map_file), + "_emscripten_memcpy_big" => Function::new_native(&mut store, ctx, crate::memory::_emscripten_memcpy_big), + "_emscripten_get_heap_size" => Function::new_native(&mut store, ctx, crate::memory::_emscripten_get_heap_size), + "_emscripten_resize_heap" => Function::new_native(&mut store, ctx, crate::memory::_emscripten_resize_heap), + "enlargeMemory" => Function::new_native(&mut store, ctx, crate::memory::enlarge_memory), + "segfault" => Function::new_native(&mut store, ctx, crate::memory::segfault), + "alignfault" => Function::new_native(&mut store, ctx, crate::memory::alignfault), + "ftfault" => Function::new_native(&mut store, ctx, crate::memory::ftfault), + "getTotalMemory" => Function::new_native(&mut store, ctx, crate::memory::get_total_memory), + "_sbrk" => Function::new_native(&mut store, ctx, crate::memory::sbrk), + "___map_file" => Function::new_native(&mut store, ctx, crate::memory::___map_file), // Exception - "___cxa_allocate_exception" => Function::new_native(ctx, crate::exception::___cxa_allocate_exception), - "___cxa_current_primary_exception" => Function::new_native(ctx, crate::exception::___cxa_current_primary_exception), - "___cxa_decrement_exception_refcount" => Function::new_native(ctx, crate::exception::___cxa_decrement_exception_refcount), - "___cxa_increment_exception_refcount" => Function::new_native(ctx, crate::exception::___cxa_increment_exception_refcount), - "___cxa_rethrow_primary_exception" => Function::new_native(ctx, crate::exception::___cxa_rethrow_primary_exception), - "___cxa_throw" => Function::new_native(ctx, crate::exception::___cxa_throw), - "___cxa_begin_catch" => Function::new_native(ctx, crate::exception::___cxa_begin_catch), - "___cxa_end_catch" => Function::new_native(ctx, crate::exception::___cxa_end_catch), - "___cxa_uncaught_exception" => Function::new_native(ctx, crate::exception::___cxa_uncaught_exception), - "___cxa_pure_virtual" => Function::new_native(ctx, crate::exception::___cxa_pure_virtual), + "___cxa_allocate_exception" => Function::new_native(&mut store, ctx, crate::exception::___cxa_allocate_exception), + "___cxa_current_primary_exception" => Function::new_native(&mut store, ctx, crate::exception::___cxa_current_primary_exception), + "___cxa_decrement_exception_refcount" => Function::new_native(&mut store, ctx, crate::exception::___cxa_decrement_exception_refcount), + "___cxa_increment_exception_refcount" => Function::new_native(&mut store, ctx, crate::exception::___cxa_increment_exception_refcount), + "___cxa_rethrow_primary_exception" => Function::new_native(&mut store, ctx, crate::exception::___cxa_rethrow_primary_exception), + "___cxa_throw" => Function::new_native(&mut store, ctx, crate::exception::___cxa_throw), + "___cxa_begin_catch" => Function::new_native(&mut store, ctx, crate::exception::___cxa_begin_catch), + "___cxa_end_catch" => Function::new_native(&mut store, ctx, crate::exception::___cxa_end_catch), + "___cxa_uncaught_exception" => Function::new_native(&mut store, ctx, crate::exception::___cxa_uncaught_exception), + "___cxa_pure_virtual" => Function::new_native(&mut store, ctx, crate::exception::___cxa_pure_virtual), // Time - "_gettimeofday" => Function::new_native(ctx, crate::time::_gettimeofday), - "_clock_getres" => Function::new_native(ctx, crate::time::_clock_getres), - "_clock_gettime" => Function::new_native(ctx, crate::time::_clock_gettime), - "_clock_settime" => Function::new_native(ctx, crate::time::_clock_settime), - "___clock_gettime" => Function::new_native(ctx, crate::time::_clock_gettime), - "_clock" => Function::new_native(ctx, crate::time::_clock), - "_difftime" => Function::new_native(ctx, crate::time::_difftime), - "_asctime" => Function::new_native(ctx, crate::time::_asctime), - "_asctime_r" => Function::new_native(ctx, crate::time::_asctime_r), - "_localtime" => Function::new_native(ctx, crate::time::_localtime), - "_time" => Function::new_native(ctx, crate::time::_time), - "_timegm" => Function::new_native(ctx, crate::time::_timegm), - "_strftime" => Function::new_native(ctx, crate::time::_strftime), - "_strftime_l" => Function::new_native(ctx, crate::time::_strftime_l), - "_localtime_r" => Function::new_native(ctx, crate::time::_localtime_r), - "_gmtime_r" => Function::new_native(ctx, crate::time::_gmtime_r), - "_ctime" => Function::new_native(ctx, crate::time::_ctime), - "_ctime_r" => Function::new_native(ctx, crate::time::_ctime_r), - "_mktime" => Function::new_native(ctx, crate::time::_mktime), - "_gmtime" => Function::new_native(ctx, crate::time::_gmtime), + "_gettimeofday" => Function::new_native(&mut store, ctx, crate::time::_gettimeofday), + "_clock_getres" => Function::new_native(&mut store, ctx, crate::time::_clock_getres), + "_clock_gettime" => Function::new_native(&mut store, ctx, crate::time::_clock_gettime), + "_clock_settime" => Function::new_native(&mut store, ctx, crate::time::_clock_settime), + "___clock_gettime" => Function::new_native(&mut store, ctx, crate::time::_clock_gettime), + "_clock" => Function::new_native(&mut store, ctx, crate::time::_clock), + "_difftime" => Function::new_native(&mut store, ctx, crate::time::_difftime), + "_asctime" => Function::new_native(&mut store, ctx, crate::time::_asctime), + "_asctime_r" => Function::new_native(&mut store, ctx, crate::time::_asctime_r), + "_localtime" => Function::new_native(&mut store, ctx, crate::time::_localtime), + "_time" => Function::new_native(&mut store, ctx, crate::time::_time), + "_timegm" => Function::new_native(&mut store, ctx, crate::time::_timegm), + "_strftime" => Function::new_native(&mut store, ctx, crate::time::_strftime), + "_strftime_l" => Function::new_native(&mut store, ctx, crate::time::_strftime_l), + "_localtime_r" => Function::new_native(&mut store, ctx, crate::time::_localtime_r), + "_gmtime_r" => Function::new_native(&mut store, ctx, crate::time::_gmtime_r), + "_ctime" => Function::new_native(&mut store, ctx, crate::time::_ctime), + "_ctime_r" => Function::new_native(&mut store, ctx, crate::time::_ctime_r), + "_mktime" => Function::new_native(&mut store, ctx, crate::time::_mktime), + "_gmtime" => Function::new_native(&mut store, ctx, crate::time::_gmtime), // Math - "sqrt" => Function::new_native(ctx, crate::math::sqrt), - "floor" => Function::new_native(ctx, crate::math::floor), - "fabs" => Function::new_native(ctx, crate::math::fabs), - "f64-rem" => Function::new_native(ctx, crate::math::f64_rem), - "_llvm_copysign_f32" => Function::new_native(ctx, crate::math::_llvm_copysign_f32), - "_llvm_copysign_f64" => Function::new_native(ctx, crate::math::_llvm_copysign_f64), - "_llvm_log10_f64" => Function::new_native(ctx, crate::math::_llvm_log10_f64), - "_llvm_log2_f64" => Function::new_native(ctx, crate::math::_llvm_log2_f64), - "_llvm_log10_f32" => Function::new_native(ctx, crate::math::_llvm_log10_f32), - "_llvm_log2_f32" => Function::new_native(ctx, crate::math::_llvm_log2_f64), - "_llvm_sin_f64" => Function::new_native(ctx, crate::math::_llvm_sin_f64), - "_llvm_cos_f64" => Function::new_native(ctx, crate::math::_llvm_cos_f64), - "_llvm_exp2_f32" => Function::new_native(ctx, crate::math::_llvm_exp2_f32), - "_llvm_exp2_f64" => Function::new_native(ctx, crate::math::_llvm_exp2_f64), - "_llvm_trunc_f64" => Function::new_native(ctx, crate::math::_llvm_trunc_f64), - "_llvm_fma_f64" => Function::new_native(ctx, crate::math::_llvm_fma_f64), - "_emscripten_random" => Function::new_native(ctx, crate::math::_emscripten_random), + "sqrt" => Function::new_native(&mut store, ctx, crate::math::sqrt), + "floor" => Function::new_native(&mut store, ctx, crate::math::floor), + "fabs" => Function::new_native(&mut store, ctx, crate::math::fabs), + "f64-rem" => Function::new_native(&mut store, ctx, crate::math::f64_rem), + "_llvm_copysign_f32" => Function::new_native(&mut store, ctx, crate::math::_llvm_copysign_f32), + "_llvm_copysign_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_copysign_f64), + "_llvm_log10_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_log10_f64), + "_llvm_log2_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_log2_f64), + "_llvm_log10_f32" => Function::new_native(&mut store, ctx, crate::math::_llvm_log10_f32), + "_llvm_log2_f32" => Function::new_native(&mut store, ctx, crate::math::_llvm_log2_f64), + "_llvm_sin_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_sin_f64), + "_llvm_cos_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_cos_f64), + "_llvm_exp2_f32" => Function::new_native(&mut store, ctx, crate::math::_llvm_exp2_f32), + "_llvm_exp2_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_exp2_f64), + "_llvm_trunc_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_trunc_f64), + "_llvm_fma_f64" => Function::new_native(&mut store, ctx, crate::math::_llvm_fma_f64), + "_emscripten_random" => Function::new_native(&mut store, ctx, crate::math::_emscripten_random), // Jump - "__setjmp" => Function::new_native(ctx, crate::jmp::__setjmp), - "__longjmp" => Function::new_native(ctx, crate::jmp::__longjmp), - "_longjmp" => Function::new_native(ctx, crate::jmp::_longjmp), - "_emscripten_longjmp" => Function::new_native(ctx, crate::jmp::_longjmp), + "__setjmp" => Function::new_native(&mut store, ctx, crate::jmp::__setjmp), + "__longjmp" => Function::new_native(&mut store, ctx, crate::jmp::__longjmp), + "_longjmp" => Function::new_native(&mut store, ctx, crate::jmp::_longjmp), + "_emscripten_longjmp" => Function::new_native(&mut store, ctx, crate::jmp::_longjmp), // Bitwise - "_llvm_bswap_i64" => Function::new_native(ctx, crate::bitwise::_llvm_bswap_i64), + "_llvm_bswap_i64" => Function::new_native(&mut store, ctx, crate::bitwise::_llvm_bswap_i64), // libc - "_execv" => Function::new_native(ctx, crate::libc::execv), - "_endpwent" => Function::new_native(ctx, crate::libc::endpwent), - "_fexecve" => Function::new_native(ctx, crate::libc::fexecve), - "_fpathconf" => Function::new_native(ctx, crate::libc::fpathconf), - "_getitimer" => Function::new_native(ctx, crate::libc::getitimer), - "_getpwent" => Function::new_native(ctx, crate::libc::getpwent), - "_killpg" => Function::new_native(ctx, crate::libc::killpg), - "_pathconf" => Function::new_native(ctx, crate::libc::pathconf), - "_siginterrupt" => Function::new_native(ctx, crate::signal::_siginterrupt), - "_setpwent" => Function::new_native(ctx, crate::libc::setpwent), - "_sigismember" => Function::new_native(ctx, crate::libc::sigismember), - "_sigpending" => Function::new_native(ctx, crate::libc::sigpending), - "___libc_current_sigrtmax" => Function::new_native(ctx, crate::libc::current_sigrtmax), - "___libc_current_sigrtmin" => Function::new_native(ctx, crate::libc::current_sigrtmin), + "_execv" => Function::new_native(&mut store, ctx, crate::libc::execv), + "_endpwent" => Function::new_native(&mut store, ctx, crate::libc::endpwent), + "_fexecve" => Function::new_native(&mut store, ctx, crate::libc::fexecve), + "_fpathconf" => Function::new_native(&mut store, ctx, crate::libc::fpathconf), + "_getitimer" => Function::new_native(&mut store, ctx, crate::libc::getitimer), + "_getpwent" => Function::new_native(&mut store, ctx, crate::libc::getpwent), + "_killpg" => Function::new_native(&mut store, ctx, crate::libc::killpg), + "_pathconf" => Function::new_native(&mut store, ctx, crate::libc::pathconf), + "_siginterrupt" => Function::new_native(&mut store, ctx, crate::signal::_siginterrupt), + "_setpwent" => Function::new_native(&mut store, ctx, crate::libc::setpwent), + "_sigismember" => Function::new_native(&mut store, ctx, crate::libc::sigismember), + "_sigpending" => Function::new_native(&mut store, ctx, crate::libc::sigpending), + "___libc_current_sigrtmax" => Function::new_native(&mut store, ctx, crate::libc::current_sigrtmax), + "___libc_current_sigrtmin" => Function::new_native(&mut store, ctx, crate::libc::current_sigrtmin), // Linking - "_dlclose" => Function::new_native(ctx, crate::linking::_dlclose), - "_dlerror" => Function::new_native(ctx, crate::linking::_dlerror), - "_dlopen" => Function::new_native(ctx, crate::linking::_dlopen), - "_dlsym" => Function::new_native(ctx, crate::linking::_dlsym), + "_dlclose" => Function::new_native(&mut store, ctx, crate::linking::_dlclose), + "_dlerror" => Function::new_native(&mut store, ctx, crate::linking::_dlerror), + "_dlopen" => Function::new_native(&mut store, ctx, crate::linking::_dlopen), + "_dlsym" => Function::new_native(&mut store, ctx, crate::linking::_dlsym), // wasm32-unknown-emscripten - "_alarm" => Function::new_native(ctx, crate::emscripten_target::_alarm), - "_atexit" => Function::new_native(ctx, crate::emscripten_target::_atexit), - "setTempRet0" => Function::new_native(ctx, crate::emscripten_target::setTempRet0), - "getTempRet0" => Function::new_native(ctx, crate::emscripten_target::getTempRet0), - "invoke_i" => Function::new_native(ctx, crate::emscripten_target::invoke_i), - "invoke_ii" => Function::new_native(ctx, crate::emscripten_target::invoke_ii), - "invoke_iii" => Function::new_native(ctx, crate::emscripten_target::invoke_iii), - "invoke_iiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiii), - "invoke_iifi" => Function::new_native(ctx, crate::emscripten_target::invoke_iifi), - "invoke_v" => Function::new_native(ctx, crate::emscripten_target::invoke_v), - "invoke_vi" => Function::new_native(ctx, crate::emscripten_target::invoke_vi), - "invoke_vj" => Function::new_native(ctx, crate::emscripten_target::invoke_vj), - "invoke_vjji" => Function::new_native(ctx, crate::emscripten_target::invoke_vjji), - "invoke_vii" => Function::new_native(ctx, crate::emscripten_target::invoke_vii), - "invoke_viii" => Function::new_native(ctx, crate::emscripten_target::invoke_viii), - "invoke_viiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiii), - "__Unwind_Backtrace" => Function::new_native(ctx, crate::emscripten_target::__Unwind_Backtrace), - "__Unwind_FindEnclosingFunction" => Function::new_native(ctx, crate::emscripten_target::__Unwind_FindEnclosingFunction), - "__Unwind_GetIPInfo" => Function::new_native(ctx, crate::emscripten_target::__Unwind_GetIPInfo), - "___cxa_find_matching_catch_2" => Function::new_native(ctx, crate::emscripten_target::___cxa_find_matching_catch_2), - "___cxa_find_matching_catch_3" => Function::new_native(ctx, crate::emscripten_target::___cxa_find_matching_catch_3), - "___cxa_free_exception" => Function::new_native(ctx, crate::emscripten_target::___cxa_free_exception), - "___resumeException" => Function::new_native(ctx, crate::emscripten_target::___resumeException), - "_dladdr" => Function::new_native(ctx, crate::emscripten_target::_dladdr), - "_pthread_attr_destroy" => Function::new_native(ctx, crate::pthread::_pthread_attr_destroy), - "_pthread_attr_getstack" => Function::new_native(ctx, crate::pthread::_pthread_attr_getstack), - "_pthread_attr_init" => Function::new_native(ctx, crate::pthread::_pthread_attr_init), - "_pthread_attr_setstacksize" => Function::new_native(ctx, crate::pthread::_pthread_attr_setstacksize), - "_pthread_cleanup_pop" => Function::new_native(ctx, crate::pthread::_pthread_cleanup_pop), - "_pthread_cleanup_push" => Function::new_native(ctx, crate::pthread::_pthread_cleanup_push), - "_pthread_cond_destroy" => Function::new_native(ctx, crate::pthread::_pthread_cond_destroy), - "_pthread_cond_init" => Function::new_native(ctx, crate::pthread::_pthread_cond_init), - "_pthread_cond_signal" => Function::new_native(ctx, crate::pthread::_pthread_cond_signal), - "_pthread_cond_timedwait" => Function::new_native(ctx, crate::pthread::_pthread_cond_timedwait), - "_pthread_cond_wait" => Function::new_native(ctx, crate::pthread::_pthread_cond_wait), - "_pthread_condattr_destroy" => Function::new_native(ctx, crate::pthread::_pthread_condattr_destroy), - "_pthread_condattr_init" => Function::new_native(ctx, crate::pthread::_pthread_condattr_init), - "_pthread_condattr_setclock" => Function::new_native(ctx, crate::pthread::_pthread_condattr_setclock), - "_pthread_create" => Function::new_native(ctx, crate::pthread::_pthread_create), - "_pthread_detach" => Function::new_native(ctx, crate::pthread::_pthread_detach), - "_pthread_equal" => Function::new_native(ctx, crate::pthread::_pthread_equal), - "_pthread_exit" => Function::new_native(ctx, crate::pthread::_pthread_exit), - "_pthread_self" => Function::new_native(ctx, crate::pthread::_pthread_self), - "_pthread_getattr_np" => Function::new_native(ctx, crate::pthread::_pthread_getattr_np), - "_pthread_getspecific" => Function::new_native(ctx, crate::pthread::_pthread_getspecific), - "_pthread_join" => Function::new_native(ctx, crate::pthread::_pthread_join), - "_pthread_key_create" => Function::new_native(ctx, crate::pthread::_pthread_key_create), - "_pthread_mutex_destroy" => Function::new_native(ctx, crate::pthread::_pthread_mutex_destroy), - "_pthread_mutex_init" => Function::new_native(ctx, crate::pthread::_pthread_mutex_init), - "_pthread_mutexattr_destroy" => Function::new_native(ctx, crate::pthread::_pthread_mutexattr_destroy), - "_pthread_mutexattr_init" => Function::new_native(ctx, crate::pthread::_pthread_mutexattr_init), - "_pthread_mutexattr_settype" => Function::new_native(ctx, crate::pthread::_pthread_mutexattr_settype), - "_pthread_once" => Function::new_native(ctx, crate::pthread::_pthread_once), - "_pthread_rwlock_destroy" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_destroy), - "_pthread_rwlock_init" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_init), - "_pthread_rwlock_rdlock" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_rdlock), - "_pthread_rwlock_unlock" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_unlock), - "_pthread_rwlock_wrlock" => Function::new_native(ctx, crate::pthread::_pthread_rwlock_wrlock), - "_pthread_setcancelstate" => Function::new_native(ctx, crate::pthread::_pthread_setcancelstate), - "_pthread_setspecific" => Function::new_native(ctx, crate::pthread::_pthread_setspecific), - "_pthread_sigmask" => Function::new_native(ctx, crate::pthread::_pthread_sigmask), - "___gxx_personality_v0" => Function::new_native(ctx, crate::emscripten_target::___gxx_personality_v0), - "_gai_strerror" => Function::new_native(ctx, crate::env::_gai_strerror), - "_getdtablesize" => Function::new_native(ctx, crate::emscripten_target::_getdtablesize), - "_gethostbyaddr" => Function::new_native(ctx, crate::emscripten_target::_gethostbyaddr), - "_gethostbyname" => Function::new_native(ctx, crate::emscripten_target::_gethostbyname), - "_gethostbyname_r" => Function::new_native(ctx, crate::emscripten_target::_gethostbyname_r), - "_getloadavg" => Function::new_native(ctx, crate::emscripten_target::_getloadavg), - "_getnameinfo" => Function::new_native(ctx, crate::emscripten_target::_getnameinfo), - "invoke_dii" => Function::new_native(ctx, crate::emscripten_target::invoke_dii), - "invoke_diiii" => Function::new_native(ctx, crate::emscripten_target::invoke_diiii), - "invoke_iiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiii), - "invoke_iiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiii), - "invoke_iiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiii), - "invoke_iiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiii), - "invoke_iiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiiii), - "invoke_iiiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiiiii), - "invoke_iiiiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_iiiiiiiiiii), - "invoke_vd" => Function::new_native(ctx, crate::emscripten_target::invoke_vd), - "invoke_viiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiii), - "invoke_viiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiii), - "invoke_viiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiii), - "invoke_viiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiii), - "invoke_viiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiiii), - "invoke_viiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiiii), - "invoke_viiiiiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiiiiiiiii), - "invoke_iij" => Function::new_native(ctx, crate::emscripten_target::invoke_iij), - "invoke_iji" => Function::new_native(ctx, crate::emscripten_target::invoke_iji), - "invoke_iiji" => Function::new_native(ctx, crate::emscripten_target::invoke_iiji), - "invoke_iiijj" => Function::new_native(ctx, crate::emscripten_target::invoke_iiijj), - "invoke_j" => Function::new_native(ctx, crate::emscripten_target::invoke_j), - "invoke_ji" => Function::new_native(ctx, crate::emscripten_target::invoke_ji), - "invoke_jii" => Function::new_native(ctx, crate::emscripten_target::invoke_jii), - "invoke_jij" => Function::new_native(ctx, crate::emscripten_target::invoke_jij), - "invoke_jjj" => Function::new_native(ctx, crate::emscripten_target::invoke_jjj), - "invoke_viiij" => Function::new_native(ctx, crate::emscripten_target::invoke_viiij), - "invoke_viiijiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiijiiii), - "invoke_viiijiiiiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viiijiiiiii), - "invoke_viij" => Function::new_native(ctx, crate::emscripten_target::invoke_viij), - "invoke_viiji" => Function::new_native(ctx, crate::emscripten_target::invoke_viiji), - "invoke_viijiii" => Function::new_native(ctx, crate::emscripten_target::invoke_viijiii), - "invoke_viijj" => Function::new_native(ctx, crate::emscripten_target::invoke_viijj), - "invoke_vij" => Function::new_native(ctx, crate::emscripten_target::invoke_vij), - "invoke_viji" => Function::new_native(ctx, crate::emscripten_target::invoke_viji), - "invoke_vijiii" => Function::new_native(ctx, crate::emscripten_target::invoke_vijiii), - "invoke_vijj" => Function::new_native(ctx, crate::emscripten_target::invoke_vijj), - "invoke_vidd" => Function::new_native(ctx, crate::emscripten_target::invoke_vidd), - "invoke_viid" => Function::new_native(ctx, crate::emscripten_target::invoke_viid), - "invoke_viidii" => Function::new_native(ctx, crate::emscripten_target::invoke_viidii), - "invoke_viidddddddd" => Function::new_native(ctx, crate::emscripten_target::invoke_viidddddddd), + "_alarm" => Function::new_native(&mut store, ctx, crate::emscripten_target::_alarm), + "_atexit" => Function::new_native(&mut store, ctx, crate::emscripten_target::_atexit), + "setTempRet0" => Function::new_native(&mut store, ctx, crate::emscripten_target::setTempRet0), + "getTempRet0" => Function::new_native(&mut store, ctx, crate::emscripten_target::getTempRet0), + "invoke_i" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_i), + "invoke_ii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_ii), + "invoke_iii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iii), + "invoke_iiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiii), + "invoke_iifi" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iifi), + "invoke_v" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_v), + "invoke_vi" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vi), + "invoke_vj" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vj), + "invoke_vjji" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vjji), + "invoke_vii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vii), + "invoke_viii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viii), + "invoke_viiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiii), + "__Unwind_Backtrace" => Function::new_native(&mut store, ctx, crate::emscripten_target::__Unwind_Backtrace), + "__Unwind_FindEnclosingFunction" => Function::new_native(&mut store, ctx, crate::emscripten_target::__Unwind_FindEnclosingFunction), + "__Unwind_GetIPInfo" => Function::new_native(&mut store, ctx, crate::emscripten_target::__Unwind_GetIPInfo), + "___cxa_find_matching_catch_2" => Function::new_native(&mut store, ctx, crate::emscripten_target::___cxa_find_matching_catch_2), + "___cxa_find_matching_catch_3" => Function::new_native(&mut store, ctx, crate::emscripten_target::___cxa_find_matching_catch_3), + "___cxa_free_exception" => Function::new_native(&mut store, ctx, crate::emscripten_target::___cxa_free_exception), + "___resumeException" => Function::new_native(&mut store, ctx, crate::emscripten_target::___resumeException), + "_dladdr" => Function::new_native(&mut store, ctx, crate::emscripten_target::_dladdr), + "_pthread_attr_destroy" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_attr_destroy), + "_pthread_attr_getstack" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_attr_getstack), + "_pthread_attr_init" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_attr_init), + "_pthread_attr_setstacksize" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_attr_setstacksize), + "_pthread_cleanup_pop" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_cleanup_pop), + "_pthread_cleanup_push" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_cleanup_push), + "_pthread_cond_destroy" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_cond_destroy), + "_pthread_cond_init" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_cond_init), + "_pthread_cond_signal" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_cond_signal), + "_pthread_cond_timedwait" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_cond_timedwait), + "_pthread_cond_wait" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_cond_wait), + "_pthread_condattr_destroy" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_condattr_destroy), + "_pthread_condattr_init" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_condattr_init), + "_pthread_condattr_setclock" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_condattr_setclock), + "_pthread_create" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_create), + "_pthread_detach" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_detach), + "_pthread_equal" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_equal), + "_pthread_exit" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_exit), + "_pthread_self" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_self), + "_pthread_getattr_np" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_getattr_np), + "_pthread_getspecific" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_getspecific), + "_pthread_join" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_join), + "_pthread_key_create" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_key_create), + "_pthread_mutex_destroy" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_mutex_destroy), + "_pthread_mutex_init" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_mutex_init), + "_pthread_mutexattr_destroy" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_mutexattr_destroy), + "_pthread_mutexattr_init" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_mutexattr_init), + "_pthread_mutexattr_settype" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_mutexattr_settype), + "_pthread_once" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_once), + "_pthread_rwlock_destroy" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_rwlock_destroy), + "_pthread_rwlock_init" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_rwlock_init), + "_pthread_rwlock_rdlock" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_rwlock_rdlock), + "_pthread_rwlock_unlock" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_rwlock_unlock), + "_pthread_rwlock_wrlock" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_rwlock_wrlock), + "_pthread_setcancelstate" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_setcancelstate), + "_pthread_setspecific" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_setspecific), + "_pthread_sigmask" => Function::new_native(&mut store, ctx, crate::pthread::_pthread_sigmask), + "___gxx_personality_v0" => Function::new_native(&mut store, ctx, crate::emscripten_target::___gxx_personality_v0), + "_gai_strerror" => Function::new_native(&mut store, ctx, crate::env::_gai_strerror), + "_getdtablesize" => Function::new_native(&mut store, ctx, crate::emscripten_target::_getdtablesize), + "_gethostbyaddr" => Function::new_native(&mut store, ctx, crate::emscripten_target::_gethostbyaddr), + "_gethostbyname" => Function::new_native(&mut store, ctx, crate::emscripten_target::_gethostbyname), + "_gethostbyname_r" => Function::new_native(&mut store, ctx, crate::emscripten_target::_gethostbyname_r), + "_getloadavg" => Function::new_native(&mut store, ctx, crate::emscripten_target::_getloadavg), + "_getnameinfo" => Function::new_native(&mut store, ctx, crate::emscripten_target::_getnameinfo), + "invoke_dii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_dii), + "invoke_diiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_diiii), + "invoke_iiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiiii), + "invoke_iiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiiiii), + "invoke_iiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiiiiii), + "invoke_iiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiiiiiii), + "invoke_iiiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiiiiiiii), + "invoke_iiiiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiiiiiiiii), + "invoke_iiiiiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiiiiiiiiii), + "invoke_vd" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vd), + "invoke_viiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiiii), + "invoke_viiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiiiii), + "invoke_viiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiiiiii), + "invoke_viiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiiiiiii), + "invoke_viiiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiiiiiiii), + "invoke_viiiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiiiiiiii), + "invoke_viiiiiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiiiiiiiii), + "invoke_iij" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iij), + "invoke_iji" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iji), + "invoke_iiji" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiji), + "invoke_iiijj" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_iiijj), + "invoke_j" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_j), + "invoke_ji" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_ji), + "invoke_jii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_jii), + "invoke_jij" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_jij), + "invoke_jjj" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_jjj), + "invoke_viiij" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiij), + "invoke_viiijiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiijiiii), + "invoke_viiijiiiiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiijiiiiii), + "invoke_viij" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viij), + "invoke_viiji" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viiji), + "invoke_viijiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viijiii), + "invoke_viijj" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viijj), + "invoke_vij" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vij), + "invoke_viji" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viji), + "invoke_vijiii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vijiii), + "invoke_vijj" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vijj), + "invoke_vidd" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_vidd), + "invoke_viid" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viid), + "invoke_viidii" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viidii), + "invoke_viidddddddd" => Function::new_native(&mut store, ctx, crate::emscripten_target::invoke_viidddddddd), // ucontext - "_getcontext" => Function::new_native(ctx, crate::ucontext::_getcontext), - "_makecontext" => Function::new_native(ctx, crate::ucontext::_makecontext), - "_setcontext" => Function::new_native(ctx, crate::ucontext::_setcontext), - "_swapcontext" => Function::new_native(ctx, crate::ucontext::_swapcontext), + "_getcontext" => Function::new_native(&mut store, ctx, crate::ucontext::_getcontext), + "_makecontext" => Function::new_native(&mut store, ctx, crate::ucontext::_makecontext), + "_setcontext" => Function::new_native(&mut store, ctx, crate::ucontext::_setcontext), + "_swapcontext" => Function::new_native(&mut store, ctx, crate::ucontext::_swapcontext), // unistd - "_confstr" => Function::new_native(ctx, crate::unistd::confstr), + "_confstr" => Function::new_native(&mut store, ctx, crate::unistd::confstr), }; // Compatibility with newer versions of Emscripten @@ -1460,31 +1467,31 @@ pub fn generate_emscripten_env( for null_function_name in globals.null_function_names.iter() { env_ns.insert( null_function_name.as_str(), - Function::new_native(ctx, nullfunc), + Function::new_native(&mut store, ctx, nullfunc), ); } let import_object: Imports = imports! { "env" => env_ns, "global" => { - "NaN" => Global::new(ctx, Value::F64(f64::NAN)), - "Infinity" => Global::new(ctx, Value::F64(f64::INFINITY)), + "NaN" => Global::new(&mut store, Value::F64(f64::NAN)), + "Infinity" => Global::new(&mut store, Value::F64(f64::INFINITY)), }, "global.Math" => { - "pow" => Function::new_native(ctx, crate::math::pow), - "exp" => Function::new_native(ctx, crate::math::exp), - "log" => Function::new_native(ctx, crate::math::log), + "pow" => Function::new_native(&mut store, ctx, crate::math::pow), + "exp" => Function::new_native(&mut store, ctx, crate::math::exp), + "log" => Function::new_native(&mut store, ctx, crate::math::log), }, "asm2wasm" => { - "f64-rem" => Function::new_native(ctx, crate::math::f64_rem), - "f64-to-int" => Function::new_native(ctx, crate::math::f64_to_int), + "f64-rem" => Function::new_native(&mut store, ctx, crate::math::f64_rem), + "f64-to-int" => Function::new_native(&mut store, ctx, crate::math::f64_to_int), }, }; import_object } -pub fn nullfunc(ctx: ContextMut<'_, EmEnv>, _x: u32) { +pub fn nullfunc(ctx: FunctionEnvMut, _x: u32) { use crate::process::abort_with_message; debug!("emscripten::nullfunc_i {}", _x); abort_with_message( diff --git a/lib/emscripten/src/libc.rs b/lib/emscripten/src/libc.rs index 3916a553b48..52ef2effcd5 100644 --- a/lib/emscripten/src/libc.rs +++ b/lib/emscripten/src/libc.rs @@ -1,77 +1,77 @@ extern crate libc; use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; #[cfg(unix)] use std::convert::TryInto; -pub fn current_sigrtmax(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn current_sigrtmax(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::current_sigrtmax"); 0 } -pub fn current_sigrtmin(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn current_sigrtmin(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::current_sigrtmin"); 0 } -pub fn endpwent(_ctx: ContextMut<'_, EmEnv>) { +pub fn endpwent(_ctx: FunctionEnvMut) { debug!("emscripten::endpwent"); } -pub fn execv(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn execv(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::execv"); 0 } -pub fn fexecve(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32) -> i32 { +pub fn fexecve(_ctx: FunctionEnvMut, _a: i32, _b: i32, _c: i32) -> i32 { debug!("emscripten::fexecve"); 0 } -pub fn fpathconf(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn fpathconf(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::fpathconf"); 0 } -pub fn getitimer(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn getitimer(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::getitimer"); 0 } -pub fn getpwent(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn getpwent(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::getpwent"); 0 } -pub fn killpg(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn killpg(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::killpg"); 0 } #[cfg(unix)] -pub fn pathconf(ctx: ContextMut<'_, EmEnv>, path_ptr: i32, name: i32) -> i32 { +pub fn pathconf(ctx: FunctionEnvMut, path_ptr: i32, name: i32) -> i32 { debug!("emscripten::pathconf"); let path = emscripten_memory_pointer!(ctx, ctx.data().memory(0), path_ptr) as *const i8; unsafe { libc::pathconf(path as *const _, name).try_into().unwrap() } } #[cfg(not(unix))] -pub fn pathconf(_ctx: ContextMut<'_, EmEnv>, _path_ptr: i32, _name: i32) -> i32 { +pub fn pathconf(_ctx: FunctionEnvMut, _path_ptr: i32, _name: i32) -> i32 { debug!("emscripten::pathconf"); 0 } -pub fn setpwent(_ctx: ContextMut<'_, EmEnv>) { +pub fn setpwent(_ctx: FunctionEnvMut) { debug!("emscripten::setpwent"); } -pub fn sigismember(_ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn sigismember(_ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::sigismember"); 0 } -pub fn sigpending(_ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn sigpending(_ctx: FunctionEnvMut, _a: i32) -> i32 { debug!("emscripten::sigpending"); 0 } diff --git a/lib/emscripten/src/linking.rs b/lib/emscripten/src/linking.rs index 585c2e46c8a..83e39c4404c 100644 --- a/lib/emscripten/src/linking.rs +++ b/lib/emscripten/src/linking.rs @@ -1,28 +1,28 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; // TODO: Need to implement. /// emscripten: dlopen(filename: *const c_char, flag: c_int) -> *mut c_void -pub fn _dlopen(mut _ctx: ContextMut<'_, EmEnv>, _filename: u32, _flag: u32) -> i32 { +pub fn _dlopen(mut _ctx: FunctionEnvMut, _filename: u32, _flag: u32) -> i32 { debug!("emscripten::_dlopen"); -1 } /// emscripten: dlclose(handle: *mut c_void) -> c_int -pub fn _dlclose(mut _ctx: ContextMut<'_, EmEnv>, _filename: u32) -> i32 { +pub fn _dlclose(mut _ctx: FunctionEnvMut, _filename: u32) -> i32 { debug!("emscripten::_dlclose"); -1 } /// emscripten: dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void -pub fn _dlsym(mut _ctx: ContextMut<'_, EmEnv>, _filepath: u32, _symbol: u32) -> i32 { +pub fn _dlsym(mut _ctx: FunctionEnvMut, _filepath: u32, _symbol: u32) -> i32 { debug!("emscripten::_dlsym"); -1 } /// emscripten: dlerror() -> *mut c_char -pub fn _dlerror(mut _ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn _dlerror(mut _ctx: FunctionEnvMut) -> i32 { debug!("emscripten::_dlerror"); -1 } diff --git a/lib/emscripten/src/lock.rs b/lib/emscripten/src/lock.rs index 118ff9d5a28..ce905d3e759 100644 --- a/lib/emscripten/src/lock.rs +++ b/lib/emscripten/src/lock.rs @@ -1,20 +1,20 @@ use crate::EmEnv; use libc::c_int; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; // NOTE: Not implemented by Emscripten -pub fn ___lock(mut _ctx: ContextMut<'_, EmEnv>, _what: c_int) { +pub fn ___lock(mut _ctx: FunctionEnvMut, _what: c_int) { debug!("emscripten::___lock {}", _what); } // NOTE: Not implemented by Emscripten -pub fn ___unlock(mut _ctx: ContextMut<'_, EmEnv>, _what: c_int) { +pub fn ___unlock(mut _ctx: FunctionEnvMut, _what: c_int) { debug!("emscripten::___unlock {}", _what); } // NOTE: Not implemented by Emscripten pub fn ___wait( - mut _ctx: ContextMut<'_, EmEnv>, + mut _ctx: FunctionEnvMut, _which: u32, _varargs: u32, _three: u32, @@ -23,7 +23,7 @@ pub fn ___wait( debug!("emscripten::___wait"); } -pub fn _flock(mut _ctx: ContextMut<'_, EmEnv>, _fd: u32, _op: u32) -> u32 { +pub fn _flock(mut _ctx: FunctionEnvMut, _fd: u32, _op: u32) -> u32 { debug!("emscripten::_flock"); 0 } diff --git a/lib/emscripten/src/math.rs b/lib/emscripten/src/math.rs index 896bc3d38f0..1940b7edbeb 100644 --- a/lib/emscripten/src/math.rs +++ b/lib/emscripten/src/math.rs @@ -1,111 +1,111 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; -pub fn _llvm_copysign_f32(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { +pub fn _llvm_copysign_f32(mut _ctx: FunctionEnvMut, x: f64, y: f64) -> f64 { x.copysign(y) } -pub fn _llvm_copysign_f64(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { +pub fn _llvm_copysign_f64(mut _ctx: FunctionEnvMut, x: f64, y: f64) -> f64 { x.copysign(y) } /// emscripten: _llvm_log10_f64 -pub fn _llvm_log10_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn _llvm_log10_f64(mut _ctx: FunctionEnvMut, value: f64) -> f64 { debug!("emscripten::_llvm_log10_f64"); value.log10() } /// emscripten: _llvm_log2_f64 -pub fn _llvm_log2_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn _llvm_log2_f64(mut _ctx: FunctionEnvMut, value: f64) -> f64 { debug!("emscripten::_llvm_log2_f64"); value.log2() } /// emscripten: _llvm_sin_f64 -pub fn _llvm_sin_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn _llvm_sin_f64(mut _ctx: FunctionEnvMut, value: f64) -> f64 { debug!("emscripten::_llvm_sin_f64"); value.sin() } /// emscripten: _llvm_cos_f64 -pub fn _llvm_cos_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn _llvm_cos_f64(mut _ctx: FunctionEnvMut, value: f64) -> f64 { debug!("emscripten::_llvm_cos_f64"); value.cos() } -pub fn _llvm_log10_f32(mut _ctx: ContextMut<'_, EmEnv>, _value: f64) -> f64 { +pub fn _llvm_log10_f32(mut _ctx: FunctionEnvMut, _value: f64) -> f64 { debug!("emscripten::_llvm_log10_f32"); -1.0 } -pub fn _llvm_log2_f32(mut _ctx: ContextMut<'_, EmEnv>, _value: f64) -> f64 { +pub fn _llvm_log2_f32(mut _ctx: FunctionEnvMut, _value: f64) -> f64 { debug!("emscripten::_llvm_log10_f32"); -1.0 } -pub fn _llvm_exp2_f32(mut _ctx: ContextMut<'_, EmEnv>, value: f32) -> f32 { +pub fn _llvm_exp2_f32(mut _ctx: FunctionEnvMut, value: f32) -> f32 { debug!("emscripten::_llvm_exp2_f32"); 2f32.powf(value) } -pub fn _llvm_exp2_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn _llvm_exp2_f64(mut _ctx: FunctionEnvMut, value: f64) -> f64 { debug!("emscripten::_llvm_exp2_f64"); 2f64.powf(value) } -pub fn _llvm_trunc_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn _llvm_trunc_f64(mut _ctx: FunctionEnvMut, value: f64) -> f64 { debug!("emscripten::_llvm_trunc_f64"); value.trunc() } -pub fn _llvm_fma_f64(mut _ctx: ContextMut<'_, EmEnv>, value: f64, a: f64, b: f64) -> f64 { +pub fn _llvm_fma_f64(mut _ctx: FunctionEnvMut, value: f64, a: f64, b: f64) -> f64 { debug!("emscripten::_llvm_fma_f64"); value.mul_add(a, b) } -pub fn _emscripten_random(mut _ctx: ContextMut<'_, EmEnv>) -> f64 { +pub fn _emscripten_random(mut _ctx: FunctionEnvMut) -> f64 { debug!("emscripten::_emscripten_random"); -1.0 } // emscripten: asm2wasm.f64-rem -pub fn f64_rem(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { +pub fn f64_rem(mut _ctx: FunctionEnvMut, x: f64, y: f64) -> f64 { debug!("emscripten::f64-rem"); x % y } // emscripten: global.Math pow -pub fn pow(mut _ctx: ContextMut<'_, EmEnv>, x: f64, y: f64) -> f64 { +pub fn pow(mut _ctx: FunctionEnvMut, x: f64, y: f64) -> f64 { x.powf(y) } // emscripten: global.Math exp -pub fn exp(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn exp(mut _ctx: FunctionEnvMut, value: f64) -> f64 { value.exp() } // emscripten: global.Math log -pub fn log(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn log(mut _ctx: FunctionEnvMut, value: f64) -> f64 { value.ln() } // emscripten: global.Math sqrt -pub fn sqrt(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn sqrt(mut _ctx: FunctionEnvMut, value: f64) -> f64 { value.sqrt() } // emscripten: global.Math floor -pub fn floor(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn floor(mut _ctx: FunctionEnvMut, value: f64) -> f64 { value.floor() } // emscripten: global.Math fabs -pub fn fabs(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> f64 { +pub fn fabs(mut _ctx: FunctionEnvMut, value: f64) -> f64 { value.abs() } // emscripten: asm2wasm.f64-to-int -pub fn f64_to_int(mut _ctx: ContextMut<'_, EmEnv>, value: f64) -> i32 { +pub fn f64_to_int(mut _ctx: FunctionEnvMut, value: f64) -> i32 { debug!("emscripten::f64_to_int {}", value); value as i32 } diff --git a/lib/emscripten/src/memory.rs b/lib/emscripten/src/memory.rs index 065aaaec429..e3fe43a2db8 100644 --- a/lib/emscripten/src/memory.rs +++ b/lib/emscripten/src/memory.rs @@ -3,12 +3,10 @@ use super::process::abort_with_message; use crate::EmEnv; use libc::{c_int, c_void, memcpy, size_t}; // TODO: investigate max pages etc. probably in Wasm Common, maybe reexport -use wasmer::{ - AsContextMut, ContextMut, Pages, WasmPtr, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE, -}; +use wasmer::{FunctionEnvMut, Pages, WasmPtr, WASM_MAX_PAGES, WASM_MIN_PAGES, WASM_PAGE_SIZE}; /// emscripten: _emscripten_memcpy_big -pub fn _emscripten_memcpy_big(ctx: ContextMut<'_, EmEnv>, dest: u32, src: u32, len: u32) -> u32 { +pub fn _emscripten_memcpy_big(ctx: FunctionEnvMut, dest: u32, src: u32, len: u32) -> u32 { debug!( "emscripten::_emscripten_memcpy_big {}, {}, {}", dest, src, len @@ -21,12 +19,12 @@ pub fn _emscripten_memcpy_big(ctx: ContextMut<'_, EmEnv>, dest: u32, src: u32, l dest } -fn get_heap_size(ctx: &ContextMut<'_, EmEnv>) -> u32 { +fn get_heap_size(ctx: &FunctionEnvMut) -> u32 { ctx.data().memory(0).size(&ctx).bytes().0 as u32 } /// emscripten: _emscripten_get_heap_size -pub fn _emscripten_get_heap_size(ctx: ContextMut<'_, EmEnv>) -> u32 { +pub fn _emscripten_get_heap_size(ctx: FunctionEnvMut) -> u32 { trace!("emscripten::_emscripten_get_heap_size"); let result = get_heap_size(&ctx); trace!("=> {}", result); @@ -42,7 +40,7 @@ fn align_up(mut val: usize, multiple: usize) -> usize { val } -fn resize_heap(ctx: &mut ContextMut<'_, EmEnv>, requested_size: u32) -> u32 { +fn resize_heap(ctx: &mut FunctionEnvMut, requested_size: u32) -> u32 { debug!("emscripten::_emscripten_resize_heap {}", requested_size); let current_memory_pages = ctx.data().memory(0).size(&ctx); let current_memory = current_memory_pages.bytes().0 as u32; @@ -67,7 +65,7 @@ fn resize_heap(ctx: &mut ContextMut<'_, EmEnv>, requested_size: u32) -> u32 { if let Ok(_pages_allocated) = ctx .data() .memory(0) - .grow(&mut ctx.as_context_mut(), Pages(amount_to_grow as u32)) + .grow(&mut ctx.as_mut(), Pages(amount_to_grow as u32)) { debug!("{} pages allocated", _pages_allocated.0); 1 @@ -78,12 +76,12 @@ fn resize_heap(ctx: &mut ContextMut<'_, EmEnv>, requested_size: u32) -> u32 { /// emscripten: _emscripten_resize_heap /// Note: this function only allows growing the size of heap -pub fn _emscripten_resize_heap(mut ctx: ContextMut<'_, EmEnv>, requested_size: u32) -> u32 { +pub fn _emscripten_resize_heap(mut ctx: FunctionEnvMut, requested_size: u32) -> u32 { resize_heap(&mut ctx, requested_size) } /// emscripten: sbrk -pub fn sbrk(mut ctx: ContextMut<'_, EmEnv>, increment: i32) -> i32 { +pub fn sbrk(mut ctx: FunctionEnvMut, increment: i32) -> i32 { debug!("emscripten::sbrk"); // let old_dynamic_top = 0; // let new_dynamic_top = 0; @@ -122,7 +120,7 @@ pub fn sbrk(mut ctx: ContextMut<'_, EmEnv>, increment: i32) -> i32 { } /// emscripten: getTotalMemory -pub fn get_total_memory(ctx: ContextMut<'_, EmEnv>) -> u32 { +pub fn get_total_memory(ctx: FunctionEnvMut) -> u32 { debug!("emscripten::get_total_memory"); // instance.memories[0].current_pages() // TODO: Fix implementation @@ -130,7 +128,7 @@ pub fn get_total_memory(ctx: ContextMut<'_, EmEnv>) -> u32 { } /// emscripten: enlargeMemory -pub fn enlarge_memory(_ctx: ContextMut<'_, EmEnv>) -> u32 { +pub fn enlarge_memory(_ctx: FunctionEnvMut) -> u32 { debug!("emscripten::enlarge_memory"); // instance.memories[0].grow(100); // TODO: Fix implementation @@ -138,7 +136,7 @@ pub fn enlarge_memory(_ctx: ContextMut<'_, EmEnv>) -> u32 { } /// emscripten: abortOnCannotGrowMemory -pub fn abort_on_cannot_grow_memory(ctx: ContextMut<'_, EmEnv>, _requested_size: u32) -> u32 { +pub fn abort_on_cannot_grow_memory(ctx: FunctionEnvMut, _requested_size: u32) -> u32 { debug!( "emscripten::abort_on_cannot_grow_memory {}", _requested_size @@ -148,32 +146,32 @@ pub fn abort_on_cannot_grow_memory(ctx: ContextMut<'_, EmEnv>, _requested_size: } /// emscripten: abortOnCannotGrowMemory -pub fn abort_on_cannot_grow_memory_old(ctx: ContextMut<'_, EmEnv>) -> u32 { +pub fn abort_on_cannot_grow_memory_old(ctx: FunctionEnvMut) -> u32 { debug!("emscripten::abort_on_cannot_grow_memory"); abort_with_message(ctx, "Cannot enlarge memory arrays!"); 0 } /// emscripten: segfault -pub fn segfault(ctx: ContextMut<'_, EmEnv>) { +pub fn segfault(ctx: FunctionEnvMut) { debug!("emscripten::segfault"); abort_with_message(ctx, "segmentation fault"); } /// emscripten: alignfault -pub fn alignfault(ctx: ContextMut<'_, EmEnv>) { +pub fn alignfault(ctx: FunctionEnvMut) { debug!("emscripten::alignfault"); abort_with_message(ctx, "alignment fault"); } /// emscripten: ftfault -pub fn ftfault(ctx: ContextMut<'_, EmEnv>) { +pub fn ftfault(ctx: FunctionEnvMut) { debug!("emscripten::ftfault"); abort_with_message(ctx, "Function table mask error"); } /// emscripten: ___map_file -pub fn ___map_file(_ctx: ContextMut<'_, EmEnv>, _one: u32, _two: u32) -> c_int { +pub fn ___map_file(_ctx: FunctionEnvMut, _one: u32, _two: u32) -> c_int { debug!("emscripten::___map_file"); // NOTE: TODO: Em returns -1 here as well. May need to implement properly -1 diff --git a/lib/emscripten/src/process.rs b/lib/emscripten/src/process.rs index 665a5fb9b10..9156f2f2c32 100644 --- a/lib/emscripten/src/process.rs +++ b/lib/emscripten/src/process.rs @@ -6,35 +6,35 @@ type PidT = libc::pid_t; type PidT = c_int; use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; -pub fn abort_with_message(ctx: ContextMut<'_, EmEnv>, message: &str) { +pub fn abort_with_message(ctx: FunctionEnvMut, message: &str) { debug!("emscripten::abort_with_message"); println!("{}", message); _abort(ctx); } /// The name of this call is `abort` but we want to avoid conflicts with libc::abort -pub fn em_abort(ctx: ContextMut<'_, EmEnv>, arg: u32) { +pub fn em_abort(ctx: FunctionEnvMut, arg: u32) { debug!("emscripten::abort"); eprintln!("Program aborted with value {}", arg); _abort(ctx); } -pub fn _abort(_ctx: ContextMut<'_, EmEnv>) { +pub fn _abort(_ctx: FunctionEnvMut) { debug!("emscripten::_abort"); unsafe { abort(); } } -pub fn _prctl(ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _prctl(ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { debug!("emscripten::_prctl"); abort_with_message(ctx, "missing function: prctl"); -1 } -pub fn _fork(_ctx: ContextMut<'_, EmEnv>) -> PidT { +pub fn _fork(_ctx: FunctionEnvMut) -> PidT { debug!("emscripten::_fork"); // unsafe { // fork() @@ -42,132 +42,132 @@ pub fn _fork(_ctx: ContextMut<'_, EmEnv>) -> PidT { -1 } -pub fn _endgrent(_ctx: ContextMut<'_, EmEnv>) { +pub fn _endgrent(_ctx: FunctionEnvMut) { debug!("emscripten::_endgrent"); } -pub fn _execve(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _execve(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_execve"); -1 } #[allow(unreachable_code)] -pub fn _exit(_ctx: ContextMut<'_, EmEnv>, status: c_int) { +pub fn _exit(_ctx: FunctionEnvMut, status: c_int) { // -> ! debug!("emscripten::_exit {}", status); unsafe { exit(status) } } -pub fn _kill(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn _kill(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::_kill"); -1 } -pub fn _sched_yield(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn _sched_yield(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::_sched_yield"); -1 } -pub fn _llvm_stacksave(_ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn _llvm_stacksave(_ctx: FunctionEnvMut) -> i32 { debug!("emscripten::_llvm_stacksave"); -1 } -pub fn _llvm_stackrestore(_ctx: ContextMut<'_, EmEnv>, _one: i32) { +pub fn _llvm_stackrestore(_ctx: FunctionEnvMut, _one: i32) { debug!("emscripten::_llvm_stackrestore"); } -pub fn _raise(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _raise(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_raise"); -1 } -pub fn _sem_init(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _sem_init(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_sem_init: {}, {}, {}", _one, _two, _three); 0 } -pub fn _sem_destroy(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _sem_destroy(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_sem_destroy"); 0 } -pub fn _sem_post(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _sem_post(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_sem_post"); -1 } -pub fn _sem_wait(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _sem_wait(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_sem_post"); -1 } #[allow(clippy::cast_ptr_alignment)] -pub fn _getgrent(_ctx: ContextMut<'_, EmEnv>) -> c_int { +pub fn _getgrent(_ctx: FunctionEnvMut) -> c_int { debug!("emscripten::_getgrent"); -1 } -pub fn _setgrent(_ctx: ContextMut<'_, EmEnv>) { +pub fn _setgrent(_ctx: FunctionEnvMut) { debug!("emscripten::_setgrent"); } -pub fn _setgroups(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn _setgroups(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::_setgroups"); -1 } -pub fn _setitimer(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _setitimer(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_setitimer"); -1 } -pub fn _usleep(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _usleep(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_usleep"); -1 } -pub fn _nanosleep(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn _nanosleep(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::_nanosleep"); -1 } -pub fn _utime(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn _utime(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::_utime"); -1 } -pub fn _utimes(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn _utimes(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::_utimes"); -1 } -pub fn _wait(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _wait(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_wait"); -1 } -pub fn _wait3(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _wait3(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_wait3"); -1 } -pub fn _wait4(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { +pub fn _wait4(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { debug!("emscripten::_wait4"); -1 } -pub fn _waitid(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { +pub fn _waitid(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32, _d: i32) -> i32 { debug!("emscripten::_waitid"); -1 } -pub fn _waitpid(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _waitpid(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_waitpid"); -1 } -pub fn abort_stack_overflow(ctx: ContextMut<'_, EmEnv>, _what: c_int) { +pub fn abort_stack_overflow(ctx: FunctionEnvMut, _what: c_int) { debug!("emscripten::abort_stack_overflow"); // TODO: Message incomplete. Need to finish em runtime data first abort_with_message( @@ -176,24 +176,24 @@ pub fn abort_stack_overflow(ctx: ContextMut<'_, EmEnv>, _what: c_int) { ); } -pub fn _llvm_trap(ctx: ContextMut<'_, EmEnv>) { +pub fn _llvm_trap(ctx: FunctionEnvMut) { debug!("emscripten::_llvm_trap"); abort_with_message(ctx, "abort!"); } -pub fn _llvm_eh_typeid_for(_ctx: ContextMut<'_, EmEnv>, _type_info_addr: u32) -> i32 { +pub fn _llvm_eh_typeid_for(_ctx: FunctionEnvMut, _type_info_addr: u32) -> i32 { debug!("emscripten::_llvm_eh_typeid_for"); -1 } -pub fn _system(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> c_int { +pub fn _system(_ctx: FunctionEnvMut, _one: i32) -> c_int { debug!("emscripten::_system"); // TODO: May need to change this Em impl to a working version eprintln!("Can't call external programs"); EAGAIN } -pub fn _popen(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> c_int { +pub fn _popen(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> c_int { debug!("emscripten::_popen"); // TODO: May need to change this Em impl to a working version eprintln!("Missing function: popen"); diff --git a/lib/emscripten/src/pthread.rs b/lib/emscripten/src/pthread.rs index 2ffd17c97a0..322a1b0326b 100644 --- a/lib/emscripten/src/pthread.rs +++ b/lib/emscripten/src/pthread.rs @@ -1,13 +1,13 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; -pub fn _pthread_attr_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_attr_destroy(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_attr_destroy"); 0 } pub fn _pthread_attr_getstack( - mut _ctx: ContextMut<'_, EmEnv>, + mut _ctx: FunctionEnvMut, _stackaddr: i32, _stacksize: i32, _other: i32, @@ -24,175 +24,175 @@ pub fn _pthread_attr_getstack( 0 } -pub fn _pthread_attr_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_attr_init(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_attr_init({})", _a); 0 } -pub fn _pthread_attr_setstacksize(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_attr_setstacksize(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_attr_setstacksize"); 0 } -pub fn _pthread_cleanup_pop(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) { +pub fn _pthread_cleanup_pop(mut _ctx: FunctionEnvMut, _a: i32) { trace!("emscripten::_pthread_cleanup_pop"); } -pub fn _pthread_cleanup_push(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) { +pub fn _pthread_cleanup_push(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) { trace!("emscripten::_pthread_cleanup_push"); } -pub fn _pthread_cond_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_cond_destroy(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_cond_destroy"); 0 } -pub fn _pthread_cond_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_cond_init(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_cond_init"); 0 } -pub fn _pthread_cond_signal(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_cond_signal(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_cond_signal"); 0 } -pub fn _pthread_cond_timedwait(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32) -> i32 { +pub fn _pthread_cond_timedwait(mut _ctx: FunctionEnvMut, _a: i32, _b: i32, _c: i32) -> i32 { trace!("emscripten::_pthread_cond_timedwait"); 0 } -pub fn _pthread_cond_wait(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_cond_wait(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_cond_wait"); 0 } -pub fn _pthread_condattr_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_condattr_destroy(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_condattr_destroy"); 0 } -pub fn _pthread_condattr_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_condattr_init(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_condattr_init"); 0 } -pub fn _pthread_condattr_setclock(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_condattr_setclock(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_condattr_setclock"); 0 } -pub fn _pthread_create(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 { +pub fn _pthread_create(mut _ctx: FunctionEnvMut, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 { trace!("emscripten::_pthread_create"); // 11 seems to mean "no" 11 } -pub fn _pthread_detach(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_detach(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_detach"); 0 } -pub fn _pthread_equal(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_equal(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_equal"); 0 } -pub fn _pthread_exit(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) { +pub fn _pthread_exit(mut _ctx: FunctionEnvMut, _a: i32) { trace!("emscripten::_pthread_exit"); } -pub fn _pthread_getattr_np(mut _ctx: ContextMut<'_, EmEnv>, _thread: i32, _attr: i32) -> i32 { +pub fn _pthread_getattr_np(mut _ctx: FunctionEnvMut, _thread: i32, _attr: i32) -> i32 { trace!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr); 0 } -pub fn _pthread_getspecific(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_getspecific(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_getspecific"); 0 } -pub fn _pthread_join(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_join(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_join"); 0 } -pub fn _pthread_self(mut _ctx: ContextMut<'_, EmEnv>) -> i32 { +pub fn _pthread_self(mut _ctx: FunctionEnvMut) -> i32 { trace!("emscripten::_pthread_self"); 0 } -pub fn _pthread_key_create(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_key_create(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_key_create"); 0 } -pub fn _pthread_mutex_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_mutex_destroy(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_mutex_destroy"); 0 } -pub fn _pthread_mutex_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_mutex_init(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_mutex_init"); 0 } -pub fn _pthread_mutexattr_destroy(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_mutexattr_destroy(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_mutexattr_destroy"); 0 } -pub fn _pthread_mutexattr_init(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_mutexattr_init(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_mutexattr_init"); 0 } -pub fn _pthread_mutexattr_settype(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_mutexattr_settype(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_mutexattr_settype"); 0 } -pub fn _pthread_once(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_once(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_once"); 0 } -pub fn _pthread_rwlock_destroy(mut _ctx: ContextMut<'_, EmEnv>, _rwlock: i32) -> i32 { +pub fn _pthread_rwlock_destroy(mut _ctx: FunctionEnvMut, _rwlock: i32) -> i32 { trace!("emscripten::_pthread_rwlock_destroy({})", _rwlock); 0 } -pub fn _pthread_rwlock_init(mut _ctx: ContextMut<'_, EmEnv>, _rwlock: i32, _attr: i32) -> i32 { +pub fn _pthread_rwlock_init(mut _ctx: FunctionEnvMut, _rwlock: i32, _attr: i32) -> i32 { trace!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr); 0 } -pub fn _pthread_rwlock_rdlock(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_rwlock_rdlock(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_rwlock_rdlock"); 0 } -pub fn _pthread_rwlock_unlock(mut _ctx: ContextMut<'_, EmEnv>, _a: i32) -> i32 { +pub fn _pthread_rwlock_unlock(mut _ctx: FunctionEnvMut, _a: i32) -> i32 { trace!("emscripten::_pthread_rwlock_unlock"); 0 } -pub fn _pthread_rwlock_wrlock(mut _ctx: ContextMut<'_, EmEnv>, _rwlock: i32) -> i32 { +pub fn _pthread_rwlock_wrlock(mut _ctx: FunctionEnvMut, _rwlock: i32) -> i32 { trace!("emscripten::_pthread_rwlock_wrlock({})", _rwlock); 0 } -pub fn _pthread_setcancelstate(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_setcancelstate(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_setcancelstate"); 0 } -pub fn _pthread_setspecific(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32) -> i32 { +pub fn _pthread_setspecific(mut _ctx: FunctionEnvMut, _a: i32, _b: i32) -> i32 { trace!("emscripten::_pthread_setspecific"); 0 } -pub fn _pthread_sigmask(mut _ctx: ContextMut<'_, EmEnv>, _a: i32, _b: i32, _c: i32) -> i32 { +pub fn _pthread_sigmask(mut _ctx: FunctionEnvMut, _a: i32, _b: i32, _c: i32) -> i32 { trace!("emscripten::_pthread_sigmask"); 0 } diff --git a/lib/emscripten/src/signal.rs b/lib/emscripten/src/signal.rs index 1e0c55f9b5a..967a15a32d0 100644 --- a/lib/emscripten/src/signal.rs +++ b/lib/emscripten/src/signal.rs @@ -1,9 +1,9 @@ // use super::varargs::VarArgs; use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; #[allow(clippy::cast_ptr_alignment)] -pub fn _sigemptyset(ctx: ContextMut<'_, EmEnv>, set: u32) -> i32 { +pub fn _sigemptyset(ctx: FunctionEnvMut, set: u32) -> i32 { debug!("emscripten::_sigemptyset"); let set_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), set) as *mut u32; unsafe { @@ -12,18 +12,18 @@ pub fn _sigemptyset(ctx: ContextMut<'_, EmEnv>, set: u32) -> i32 { 0 } -pub fn _sigaction(_ctx: ContextMut<'_, EmEnv>, _signum: u32, _act: u32, _oldact: u32) -> i32 { +pub fn _sigaction(_ctx: FunctionEnvMut, _signum: u32, _act: u32, _oldact: u32) -> i32 { debug!("emscripten::_sigaction {}, {}, {}", _signum, _act, _oldact); 0 } -pub fn _siginterrupt(_ctx: ContextMut<'_, EmEnv>, _a: u32, _b: u32) -> i32 { +pub fn _siginterrupt(_ctx: FunctionEnvMut, _a: u32, _b: u32) -> i32 { debug!("emscripten::_siginterrupt {}, {}", _a, _b); 0 } #[allow(clippy::cast_ptr_alignment)] -pub fn _sigaddset(ctx: ContextMut<'_, EmEnv>, set: u32, signum: u32) -> i32 { +pub fn _sigaddset(ctx: FunctionEnvMut, set: u32, signum: u32) -> i32 { debug!("emscripten::_sigaddset {}, {}", set, signum); let set_addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), set) as *mut u32; unsafe { @@ -32,17 +32,17 @@ pub fn _sigaddset(ctx: ContextMut<'_, EmEnv>, set: u32, signum: u32) -> i32 { 0 } -pub fn _sigsuspend(_ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _sigsuspend(_ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_sigsuspend"); -1 } -pub fn _sigprocmask(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32, _three: i32) -> i32 { +pub fn _sigprocmask(_ctx: FunctionEnvMut, _one: i32, _two: i32, _three: i32) -> i32 { debug!("emscripten::_sigprocmask"); 0 } -pub fn _signal(_ctx: ContextMut<'_, EmEnv>, _sig: u32, _two: i32) -> i32 { +pub fn _signal(_ctx: FunctionEnvMut, _sig: u32, _two: i32) -> i32 { debug!("emscripten::_signal ({})", _sig); 0 } diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 6b8dc0ffd47..2fb48f4350d 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -48,10 +48,10 @@ use super::env; #[allow(unused_imports)] use std::io::Error; use std::slice; -use wasmer::{AsContextMut, ContextMut, WasmPtr}; +use wasmer::{FunctionEnvMut, WasmPtr}; /// exit -pub fn ___syscall1(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) { +pub fn ___syscall1(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) { debug!("emscripten::___syscall1 (exit) {}", _which); let status: i32 = varargs.get(&ctx); unsafe { @@ -60,7 +60,7 @@ pub fn ___syscall1(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarAr } /// read -pub fn ___syscall3(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall3(ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall3 (read) {}", _which); let fd: i32 = varargs.get(&ctx); @@ -74,7 +74,7 @@ pub fn ___syscall3(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs } /// write -pub fn ___syscall4(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall4(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall4 (write) {}", _which); let fd: i32 = varargs.get(&ctx); let buf: i32 = varargs.get(&ctx); @@ -85,7 +85,7 @@ pub fn ___syscall4(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarAr } /// close -pub fn ___syscall6(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall6(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall6 (close) {}", _which); let fd: i32 = varargs.get(&ctx); debug!("fd: {}", fd); @@ -93,7 +93,7 @@ pub fn ___syscall6(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarAr } // chdir -pub fn ___syscall12(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall12(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall12 (chdir) {}", _which); let path_ptr = varargs.get_str(&ctx); let real_path_owned = get_cstr_path(ctx, path_ptr as *const _); @@ -111,63 +111,63 @@ pub fn ___syscall12(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarA ret } -pub fn ___syscall10(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall10(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall10"); -1 } -pub fn ___syscall14(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall14(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall14"); -1 } -pub fn ___syscall15(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall15(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall15"); -1 } // getpid -pub fn ___syscall20(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall20(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall20 (getpid)"); unsafe { getpid() } } -pub fn ___syscall21(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall21(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall21"); -1 } -pub fn ___syscall25(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall25(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall25"); -1 } -pub fn ___syscall29(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall29(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall29"); -1 } -pub fn ___syscall32(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall32(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall32"); -1 } -pub fn ___syscall33(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall33(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall33"); -1 } -pub fn ___syscall36(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall36(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall36"); -1 } // rename -pub fn ___syscall38(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall38(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall38 (rename)"); let old_path = varargs.get_str(&ctx); let new_path = varargs.get_str(&ctx); - let real_old_path_owned = get_cstr_path(ctx.as_context_mut(), old_path as *const _); + let real_old_path_owned = get_cstr_path(ctx.as_mut(), old_path as *const _); let real_old_path = if let Some(ref rp) = real_old_path_owned { rp.as_c_str().as_ptr() } else { @@ -190,7 +190,7 @@ pub fn ___syscall38(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } // rmdir -pub fn ___syscall40(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall40(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall40 (rmdir)"); let pathname_addr = varargs.get_str(&ctx); let real_path_owned = get_cstr_path(ctx, pathname_addr as *const _); @@ -203,7 +203,7 @@ pub fn ___syscall40(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarA } // pipe -pub fn ___syscall42(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall42(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall42 (pipe)"); // offset to a file descriptor, which contains a read end and write end, 2 integers let fd_offset: u32 = varargs.get(&ctx); @@ -230,28 +230,28 @@ pub fn ___syscall42(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarA result } -pub fn ___syscall51(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall51(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall51"); -1 } -pub fn ___syscall52(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall52(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall52"); -1 } -pub fn ___syscall53(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall53(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall53"); -1 } -pub fn ___syscall60(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall60(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall60"); -1 } // dup2 -pub fn ___syscall63(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall63(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall63 (dup2) {}", _which); let src: i32 = varargs.get(&ctx); @@ -261,97 +261,97 @@ pub fn ___syscall63(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarA } // getppid -pub fn ___syscall64(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall64(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall64 (getppid)"); unsafe { getpid() } } -pub fn ___syscall66(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall66(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall66"); -1 } -pub fn ___syscall75(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall75(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall75"); -1 } -pub fn ___syscall91(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall91(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall91 - stub"); 0 } -pub fn ___syscall96(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall96(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall96"); -1 } -pub fn ___syscall97(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall97(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall97"); -1 } -pub fn ___syscall110(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall110(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall110"); -1 } -pub fn ___syscall121(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall121(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall121"); -1 } -pub fn ___syscall125(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall125(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall125"); -1 } -pub fn ___syscall133(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall133(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall133"); -1 } -pub fn ___syscall144(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall144(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall144"); -1 } -pub fn ___syscall147(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall147(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall147"); -1 } -pub fn ___syscall150(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall150(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall150"); -1 } -pub fn ___syscall151(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall151(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall151"); -1 } -pub fn ___syscall152(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall152(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall152"); -1 } -pub fn ___syscall153(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall153(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall153"); -1 } -pub fn ___syscall163(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall163(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall163"); -1 } // getcwd -pub fn ___syscall183(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall183(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall183"); let buf_offset: WasmPtr = varargs.get(&ctx); let _size: c_int = varargs.get(&ctx); - let path = get_current_directory(ctx.as_context_mut()); + let path = get_current_directory(ctx.as_mut()); let path_string = path.unwrap().display().to_string(); let len = path_string.len(); let memory = ctx.data().memory(0); @@ -365,7 +365,7 @@ pub fn ___syscall183(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } // mmap2 -pub fn ___syscall192(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall192(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall192 (mmap2) {}", _which); let _addr: i32 = varargs.get(&ctx); let len: u32 = varargs.get(&ctx); @@ -379,13 +379,13 @@ pub fn ___syscall192(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: ); if fd == -1 { - let ptr = env::call_memalign(ctx.as_context_mut(), 16384, len); + let ptr = env::call_memalign(&mut ctx, 16384, len); if ptr == 0 { // ENOMEM return -12; } let real_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), ptr) as *const u8; - env::call_memset(ctx, ptr, 0, len); + env::call_memset(&mut ctx, ptr, 0, len); for i in 0..(len as usize) { unsafe { assert_eq!(*real_ptr.add(i), 0); @@ -400,7 +400,7 @@ pub fn ___syscall192(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } /// lseek -pub fn ___syscall140(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall140(ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs) -> i32 { // -> c_int debug!("emscripten::___syscall140 (lseek) {}", _which); let fd: i32 = varargs.get(&ctx); @@ -429,7 +429,7 @@ pub fn ___syscall140(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarAr /// readv #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall145(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall145(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall145 (readv) {}", _which); @@ -468,7 +468,7 @@ pub fn ___syscall145(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var // writev #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall146(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall146(ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs) -> i32 { // -> ssize_t debug!("emscripten::___syscall146 (writev) {}", _which); let fd: i32 = varargs.get(&ctx); @@ -511,7 +511,7 @@ pub fn ___syscall146(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarAr ret as _ } -pub fn ___syscall191(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall191(ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs) -> i32 { let _resource: i32 = varargs.get(&ctx); debug!( "emscripten::___syscall191 - mostly stub, resource: {}", @@ -528,18 +528,18 @@ pub fn ___syscall191(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarAr 0 } -pub fn ___syscall193(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall193(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall193"); -1 } // stat64 -pub fn ___syscall195(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall195(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall195 (stat64) {}", _which); let pathname_addr = varargs.get_str(&ctx); let buf: u32 = varargs.get(&ctx); - let real_path_owned = get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); + let real_path_owned = get_cstr_path(ctx.as_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -565,7 +565,7 @@ pub fn ___syscall195(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } // fstat64 -pub fn ___syscall197(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall197(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall197 (fstat64) {}", _which); let fd: c_int = varargs.get(&ctx); @@ -584,129 +584,129 @@ pub fn ___syscall197(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var 0 } -pub fn ___syscall209(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall209(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall209"); -1 } -pub fn ___syscall211(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall211(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall211"); -1 } -pub fn ___syscall218(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall218(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall218"); -1 } -pub fn ___syscall268(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall268(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall268"); -1 } -pub fn ___syscall269(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall269(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall269"); -1 } -pub fn ___syscall272(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall272(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall272"); -1 } -pub fn ___syscall295(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall295(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall295"); -1 } -pub fn ___syscall296(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall296(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall296"); -1 } -pub fn ___syscall297(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall297(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall297"); -1 } -pub fn ___syscall298(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall298(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall298"); -1 } -pub fn ___syscall300(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall300(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall300"); -1 } -pub fn ___syscall301(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall301(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall301"); -1 } -pub fn ___syscall302(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall302(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall302"); -1 } -pub fn ___syscall303(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall303(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall303"); -1 } -pub fn ___syscall304(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall304(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall304"); -1 } -pub fn ___syscall305(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall305(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall305"); -1 } -pub fn ___syscall306(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall306(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall306"); -1 } -pub fn ___syscall307(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall307(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall307"); -1 } -pub fn ___syscall308(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall308(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall308"); -1 } // utimensat -pub fn ___syscall320(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall320(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall320 (utimensat), {}", _which); 0 } -pub fn ___syscall331(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall331(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall331"); -1 } -pub fn ___syscall333(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall333(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall333"); -1 } -pub fn ___syscall334(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall334(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall334"); -1 } -pub fn ___syscall337(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall337(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall337"); -1 } // prlimit64 -pub fn ___syscall340(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall340(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall340 (prlimit64), {}", _which); // NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway. let _pid: i32 = varargs.get(&ctx); @@ -732,7 +732,7 @@ pub fn ___syscall340(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var 0 } -pub fn ___syscall345(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall345(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall345"); -1 } diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index ea402a33a63..4ef741dd75e 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -81,7 +81,7 @@ use libc::{ // TCGETS, // TCSETSW, }; -use wasmer::{AsContextMut, ContextMut, ValueType, WasmPtr}; +use wasmer::{FunctionEnvMut, ValueType, WasmPtr}; // They are not exposed in in Rust libc in macOS const TCGETS: u64 = 0x5401; @@ -157,12 +157,12 @@ use libc::SO_NOSIGPIPE; const SO_NOSIGPIPE: c_int = 0; /// open -pub fn ___syscall5(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall5(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall5 (open) {}", _which); let pathname_addr = varargs.get_str(&ctx); let flags: i32 = varargs.get(&ctx); let mode: u32 = varargs.get(&ctx); - let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); + let real_path_owned = utils::get_cstr_path(ctx, pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -181,7 +181,7 @@ pub fn ___syscall5(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: V } /// link -pub fn ___syscall9(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall9(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall9 (link) {}", _which); let oldname_ptr = varargs.get_str(&ctx); @@ -197,7 +197,7 @@ pub fn ___syscall9(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarAr } /// getrusage -pub fn ___syscall77(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall77(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall77 (getrusage) {}", _which); let resource: c_int = varargs.get(&ctx); @@ -209,18 +209,18 @@ pub fn ___syscall77(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarA } /// symlink -pub fn ___syscall83(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall83(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall83 (symlink) {}", _which); let path1 = varargs.get_str(&ctx); let path2 = varargs.get_str(&ctx); - let real_path1_owned = utils::get_cstr_path(ctx.as_context_mut(), path1 as *const _); + let real_path1_owned = utils::get_cstr_path(ctx.as_mut(), path1 as *const _); let real_path1 = if let Some(ref rp) = real_path1_owned { rp.as_c_str().as_ptr() } else { path1 }; - let real_path2_owned = utils::get_cstr_path(ctx.as_context_mut(), path2 as *const _); + let real_path2_owned = utils::get_cstr_path(ctx, path2 as *const _); let real_path2 = if let Some(ref rp) = real_path2_owned { rp.as_c_str().as_ptr() } else { @@ -237,13 +237,13 @@ pub fn ___syscall83(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } /// readlink -pub fn ___syscall85(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> i32 { +pub fn ___syscall85(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall85 (readlink)"); let pathname_addr = varargs.get_str(&ctx); let buf = varargs.get_str(&ctx); // let buf_addr: i32 = varargs.get(&ctx); let buf_size: i32 = varargs.get(&ctx); - let real_path_owned = get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); + let real_path_owned = get_cstr_path(ctx, pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -266,7 +266,7 @@ pub fn ___syscall85(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } /// ftruncate64 -pub fn ___syscall194(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall194(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall194 (ftruncate64) {}", _which); let _fd: c_int = varargs.get(&ctx); let _length: i64 = varargs.get(&ctx); @@ -283,10 +283,10 @@ pub fn ___syscall194(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// lchown -pub fn ___syscall198(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall198(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall198 (lchown) {}", _which); let path_ptr = varargs.get_str(&ctx); - let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), path_ptr as *const _); + let real_path_owned = utils::get_cstr_path(ctx.as_mut(), path_ptr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -306,7 +306,7 @@ pub fn ___syscall198(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } /// getgroups -pub fn ___syscall205(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall205(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall205 (getgroups) {}", _which); let ngroups_max: c_int = varargs.get(&ctx); let groups: c_int = varargs.get(&ctx); @@ -323,11 +323,11 @@ pub fn ___syscall205(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } // chown -pub fn ___syscall212(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall212(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); let pathname_addr = varargs.get_str(&ctx); - let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); + let real_path_owned = utils::get_cstr_path(ctx.as_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -340,7 +340,7 @@ pub fn ___syscall212(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } /// madvise -pub fn ___syscall219(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall219(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); let addr_ptr: c_int = varargs.get(&ctx); @@ -353,10 +353,10 @@ pub fn ___syscall219(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// access -pub fn ___syscall33(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall33(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall33 (access) {}", _which); let path = varargs.get_str(&ctx); - let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), path as *const _); + let real_path_owned = utils::get_cstr_path(ctx.as_mut(), path as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -374,17 +374,17 @@ pub fn ___syscall33(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } /// nice -pub fn ___syscall34(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall34(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall34 (nice) {}", _which); let inc_r: c_int = varargs.get(&ctx); unsafe { nice(inc_r) } } // mkdir -pub fn ___syscall39(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall39(mut ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", _which); let pathname_addr = varargs.get_str(&ctx); - let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), pathname_addr as *const _); + let real_path_owned = utils::get_cstr_path(ctx.as_mut(), pathname_addr as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -395,20 +395,20 @@ pub fn ___syscall39(mut ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: } /// dup -pub fn ___syscall41(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall41(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall41 (dup) {}", _which); let fd: c_int = varargs.get(&ctx); unsafe { dup(fd) } } /// getgid32 -pub fn ___syscall200(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall200(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall200 (getgid32)"); unsafe { getgid() as i32 } } // geteuid32 -pub fn ___syscall201(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall201(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (geteuid32)"); unsafe { // Maybe fix: Emscripten returns 0 always @@ -417,7 +417,7 @@ pub fn ___syscall201(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { } // getegid32 -pub fn ___syscall202(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall202(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { // gid_t debug!("emscripten::___syscall202 (getegid32)"); unsafe { @@ -427,7 +427,7 @@ pub fn ___syscall202(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { } /// fchown -pub fn ___syscall207(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall207(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall207 (fchown) {}", _which); let fd: c_int = varargs.get(&ctx); let owner: uid_t = varargs.get(&ctx); @@ -436,7 +436,7 @@ pub fn ___syscall207(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// dup3 -pub fn ___syscall330(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> pid_t { +pub fn ___syscall330(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> pid_t { // Implementation based on description at https://linux.die.net/man/2/dup3 debug!("emscripten::___syscall330 (dup3)"); let oldfd: c_int = varargs.get(&ctx); @@ -474,7 +474,7 @@ pub fn ___syscall330(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// ioctl -pub fn ___syscall54(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall54(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall54 (ioctl) {}", _which); let fd: i32 = varargs.get(&ctx); @@ -517,7 +517,7 @@ const SOCK_CLOEXC: i32 = 0x80000; // socketcall #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall102(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall102(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall102 (socketcall) {}", _which); let call: u32 = varargs.get(&ctx); let mut socket_varargs: VarArgs = varargs.get(&ctx); @@ -833,7 +833,7 @@ fn translate_socket_name_flag(name: i32) -> i32 { } /// getpgid -pub fn ___syscall132(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall132(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall132 (getpgid)"); let pid: pid_t = varargs.get(&ctx); @@ -855,7 +855,7 @@ pub struct EmPollFd { } /// poll -pub fn ___syscall168(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall168(ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall168(poll)"); let fds: WasmPtr = varargs.get(&ctx); let nfds: u32 = varargs.get(&ctx); @@ -874,7 +874,7 @@ pub fn ___syscall168(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarAr } // pread -pub fn ___syscall180(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall180(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", _which); let fd: i32 = varargs.get(&ctx); let buf: u32 = varargs.get(&ctx); @@ -891,7 +891,7 @@ pub fn ___syscall180(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } // pwrite -pub fn ___syscall181(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall181(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall181 (pwrite) {}", _which); let fd: i32 = varargs.get(&ctx); let buf: u32 = varargs.get(&ctx); @@ -912,7 +912,7 @@ pub fn ___syscall181(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// fchmod -pub fn ___syscall94(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall94(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fchmod) {}", _which); let fd: c_int = varargs.get(&ctx); let mode: mode_t = varargs.get(&ctx); @@ -921,7 +921,7 @@ pub fn ___syscall94(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarA /// wait4 #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall114(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> pid_t { +pub fn ___syscall114(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall114 (wait4)"); let pid: pid_t = varargs.get(&ctx); let status: u32 = varargs.get(&ctx); @@ -939,7 +939,7 @@ pub fn ___syscall114(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// fsync -pub fn ___syscall118(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall118(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fsync) {}", _which); let fd: c_int = varargs.get(&ctx); unsafe { fsync(fd) } @@ -947,7 +947,7 @@ pub fn ___syscall118(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var // select #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall142(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall142(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall142 (newselect) {}", _which); let nfds: i32 = varargs.get(&ctx); @@ -969,7 +969,7 @@ pub fn ___syscall142(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// fdatasync -pub fn ___syscall148(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall148(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall148 (fdatasync) {}", _which); let fd: i32 = varargs.get(&ctx); @@ -978,7 +978,7 @@ pub fn ___syscall148(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } // setpgid -pub fn ___syscall57(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall57(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall57 (setpgid) {}", _which); let pid: i32 = varargs.get(&ctx); @@ -994,7 +994,7 @@ pub fn ___syscall57(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarA /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall122(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall122 (uname) {}", _which); let buf: u32 = varargs.get(&ctx); debug!("=> buf: {}", buf); @@ -1003,10 +1003,10 @@ pub fn ___syscall122(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// lstat64 -pub fn ___syscall196(mut ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall196(mut ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs) -> i32 { debug!("emscripten::___syscall196 (lstat64) {}", _which); let path = varargs.get_str(&ctx); - let real_path_owned = utils::get_cstr_path(ctx.as_context_mut(), path as *const _); + let real_path_owned = utils::get_cstr_path(ctx.as_mut(), path as *const _); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -1036,7 +1036,7 @@ pub fn ___syscall196(mut ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: V } // getuid -pub fn ___syscall199(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall199(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall199 (getuid)"); let uid = unsafe { getuid() as _ }; debug!(" => {}", uid); @@ -1046,7 +1046,7 @@ pub fn ___syscall199(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { // getdents // dirent structure is // i64, i64, u16 (280), i8, [i8; 256] -pub fn ___syscall220(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarArgs) -> i32 { +pub fn ___syscall220(ctx: FunctionEnvMut, _which: i32, mut varargs: VarArgs) -> i32 { use super::super::env::get_emscripten_data; let fd: i32 = varargs.get(&ctx); @@ -1111,7 +1111,7 @@ pub fn ___syscall220(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarAr } // fcntl64 -pub fn ___syscall221(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall221(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall221 (fcntl64) {}", _which); let fd: i32 = varargs.get(&ctx); let cmd: i32 = varargs.get(&ctx); @@ -1129,7 +1129,7 @@ pub fn ___syscall221(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: Var } /// fallocate -pub fn ___syscall324(ctx: ContextMut<'_, EmEnv>, _which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall324(ctx: FunctionEnvMut, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall324 (fallocate) {}", _which); let _fd: c_int = varargs.get(&ctx); let _mode: c_int = varargs.get(&ctx); diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows.rs index 3c16821c940..705dd19905c 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows.rs @@ -8,18 +8,18 @@ use std::ffi::CString; use std::fs::File; use std::io::Write; use std::os::raw::c_int; -use wasmer::{AsContextMut, ContextMut}; +use wasmer::FunctionEnvMut; #[allow(non_camel_case_types)] type pid_t = c_int; /// open -pub fn ___syscall5(mut ctx: ContextMut<'_, EmEnv>, which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall5(mut ctx: FunctionEnvMut, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall5 (open) {}", which); #[cfg(not(feature = "debug"))] let _ = which; let pathname_addr = varargs.get_str(&ctx); - let real_path_owned = get_cstr_path(ctx.as_context_mut(), pathname_addr); + let real_path_owned = get_cstr_path(ctx.as_mut(), pathname_addr); let real_path = if let Some(ref rp) = real_path_owned { rp.as_c_str().as_ptr() } else { @@ -45,7 +45,7 @@ pub fn ___syscall5(mut ctx: ContextMut<'_, EmEnv>, which: c_int, mut varargs: Va getrandom::getrandom(&mut random_bytes).unwrap(); let _ = urandom_file.write_all(&random_bytes).unwrap(); // put the file path string into wasm memory - let urandom_file_offset = unsafe { copy_cstr_into_wasm(ctx.as_context_mut(), ptr) }; + let urandom_file_offset = unsafe { copy_cstr_into_wasm(&mut ctx, ptr) }; let raw_pointer_to_urandom_file = emscripten_memory_pointer!(ctx, memory, urandom_file_offset) as *const i8; let fd = unsafe { open(raw_pointer_to_urandom_file, flags, mode) }; @@ -67,19 +67,19 @@ pub fn ___syscall5(mut ctx: ContextMut<'_, EmEnv>, which: c_int, mut varargs: Va } /// link -pub fn ___syscall9(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall9(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall9 (link) {}", _which); unimplemented!("emscripten::___syscall9 (link) {}", _which); } /// ftruncate64 -pub fn ___syscall194(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall194(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall194 - stub"); unimplemented!("emscripten::___syscall194 - stub") } // chown -pub fn ___syscall212(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall212(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -87,19 +87,19 @@ pub fn ___syscall212(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Va } /// access -pub fn ___syscall33(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall33(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall33 (access) {}", _which); unimplemented!("emscripten::___syscall33 (access) {}", _which); } /// nice -pub fn ___syscall34(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall34(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall34 (nice) {}", _which); unimplemented!("emscripten::___syscall34 (nice) {}", _which); } // mkdir -pub fn ___syscall39(ctx: ContextMut<'_, EmEnv>, which: c_int, mut varargs: VarArgs) -> c_int { +pub fn ___syscall39(ctx: FunctionEnvMut, which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -114,80 +114,80 @@ pub fn ___syscall39(ctx: ContextMut<'_, EmEnv>, which: c_int, mut varargs: VarAr } /// dup -pub fn ___syscall41(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall41(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall41 (dup) {}", _which); unimplemented!("emscripten::___syscall41 (dup) {}", _which); } /// getrusage -pub fn ___syscall77(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall77(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall77 (getrusage) {}", _which); unimplemented!("emscripten::___syscall77 (getrusage) {}", _which); } /// symlink -pub fn ___syscall83(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall83(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall83 (symlink) {}", _which); unimplemented!("emscripten::___syscall83 (symlink) {}", _which); } /// readlink -pub fn ___syscall85(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall85(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall85 (readlink) {}", _which); -1 } /// getpgid -pub fn ___syscall132(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall132(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall132 (getpgid)"); -1 } /// lchown -pub fn ___syscall198(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall198(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall198 (lchown) {}", _which); unimplemented!("emscripten::___syscall198 (lchown) {}", _which); } /// getgid32 -pub fn ___syscall200(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall200(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall200 (getgid32)"); unimplemented!("emscripten::___syscall200 (getgid32)"); } // geteuid32 -pub fn ___syscall201(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall201(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (geteuid32)"); unimplemented!("emscripten::___syscall201 (geteuid32)"); } // getegid32 -pub fn ___syscall202(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall202(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { // gid_t debug!("emscripten::___syscall202 (getegid32)"); unimplemented!("emscripten::___syscall202 (getegid32)"); } /// getgroups -pub fn ___syscall205(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall205(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall205 (getgroups) {}", _which); unimplemented!("emscripten::___syscall205 (getgroups) {}", _which); } /// madvise -pub fn ___syscall219(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall219(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); unimplemented!("emscripten::___syscall212 (chown) {}", _which); } /// dup3 -pub fn ___syscall330(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> pid_t { +pub fn ___syscall330(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall330 (dup3)"); -1 } /// ioctl -pub fn ___syscall54(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall54(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall54 (ioctl) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -195,14 +195,14 @@ pub fn ___syscall54(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Var } /// fchmod -pub fn ___syscall94(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall94(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fchmod) {}", _which); unimplemented!("emscripten::___syscall118 (fchmod) {}", _which); } // socketcall #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall102(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall102(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall102 (socketcall) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -210,13 +210,13 @@ pub fn ___syscall102(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Va } /// fsync -pub fn ___syscall118(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall118(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall118 (fsync) {}", _which); unimplemented!("emscripten::___syscall118 (fsync) {}", _which); } // pread -pub fn ___syscall180(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall180(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -224,7 +224,7 @@ pub fn ___syscall180(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Va } // pwrite -pub fn ___syscall181(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall181(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall181 (pwrite) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -233,14 +233,14 @@ pub fn ___syscall181(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Va /// wait4 #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall114(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> pid_t { +pub fn ___syscall114(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> pid_t { debug!("emscripten::___syscall114 (wait4)"); -1 } // select #[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall142(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall142(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall142 (newselect) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -248,13 +248,13 @@ pub fn ___syscall142(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Va } /// fdatasync -pub fn ___syscall148(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall148(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall148 (fdatasync) {}", _which); unimplemented!("emscripten::___syscall148 (fdatasync) {}", _which); } // setpgid -pub fn ___syscall57(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall57(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall57 (setpgid) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -263,7 +263,7 @@ pub fn ___syscall57(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Var /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall122(_ctx: FunctionEnvMut, which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall122 (uname) {}", which); #[cfg(not(feature = "debug"))] let _ = which; @@ -271,43 +271,43 @@ pub fn ___syscall122(_ctx: ContextMut<'_, EmEnv>, which: c_int, mut _varargs: Va } /// poll -pub fn ___syscall168(_ctx: ContextMut<'_, EmEnv>, _which: i32, _varargs: VarArgs) -> i32 { +pub fn ___syscall168(_ctx: FunctionEnvMut, _which: i32, _varargs: VarArgs) -> i32 { debug!("emscripten::___syscall168(poll) - stub"); -1 } /// lstat64 -pub fn ___syscall196(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall196(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall196 (lstat64) - stub"); -1 } // getuid -pub fn ___syscall199(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall199(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall199 (getuid)"); -1 } // getdents -pub fn ___syscall220(_ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn ___syscall220(_ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall220"); -1 } // fcntl64 -pub fn ___syscall221(_ctx: ContextMut<'_, EmEnv>, _which: c_int, mut _varargs: VarArgs) -> c_int { +pub fn ___syscall221(_ctx: FunctionEnvMut, _which: c_int, mut _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall221 (fcntl64) {}", _which); -1 } /// fchown -pub fn ___syscall207(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall207(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall207 (fchown) {}", _which); unimplemented!("emscripten::___syscall207 (fchown) {}", _which) } /// fallocate -pub fn ___syscall324(_ctx: ContextMut<'_, EmEnv>, _which: c_int, _varargs: VarArgs) -> c_int { +pub fn ___syscall324(_ctx: FunctionEnvMut, _which: c_int, _varargs: VarArgs) -> c_int { debug!("emscripten::___syscall324 (fallocate) {}", _which); unimplemented!("emscripten::___syscall324 (fallocate) {}", _which) } diff --git a/lib/emscripten/src/time.rs b/lib/emscripten/src/time.rs index aa32da5d01c..63c90b13fc3 100644 --- a/lib/emscripten/src/time.rs +++ b/lib/emscripten/src/time.rs @@ -13,7 +13,7 @@ use std::ffi::CString; #[cfg(target_os = "windows")] use libc::time_t; -use wasmer::{AsContextMut, ContextMut}; +use wasmer::FunctionEnvMut; #[cfg(target_os = "windows")] #[allow(non_camel_case_types)] @@ -52,7 +52,7 @@ const CLOCK_MONOTONIC_COARSE: clockid_t = 6; /// emscripten: _gettimeofday #[allow(clippy::cast_ptr_alignment)] -pub fn _gettimeofday(ctx: ContextMut<'_, EmEnv>, tp: c_int, tz: c_int) -> c_int { +pub fn _gettimeofday(ctx: FunctionEnvMut, tp: c_int, tz: c_int) -> c_int { debug!("emscripten::_gettimeofday {} {}", tp, tz); #[repr(C)] struct GuestTimeVal { @@ -76,7 +76,7 @@ pub fn _gettimeofday(ctx: ContextMut<'_, EmEnv>, tp: c_int, tz: c_int) -> c_int 0 } -pub fn _clock_getres(mut _ctx: ContextMut<'_, EmEnv>, _clk_id: i32, _tp: i32) -> i32 { +pub fn _clock_getres(mut _ctx: FunctionEnvMut, _clk_id: i32, _tp: i32) -> i32 { debug!("emscripten::_clock_getres"); // clock_getres(clk_id, tp) 0 @@ -84,7 +84,7 @@ pub fn _clock_getres(mut _ctx: ContextMut<'_, EmEnv>, _clk_id: i32, _tp: i32) -> /// emscripten: _clock_gettime #[allow(clippy::cast_ptr_alignment)] -pub fn _clock_gettime(ctx: ContextMut<'_, EmEnv>, clk_id: clockid_t, tp: c_int) -> c_int { +pub fn _clock_gettime(ctx: FunctionEnvMut, clk_id: clockid_t, tp: c_int) -> c_int { debug!("emscripten::_clock_gettime {} {}", clk_id, tp); // debug!("Memory {:?}", ctx.memory(0)[..]); #[repr(C)] @@ -116,41 +116,41 @@ pub fn _clock_gettime(ctx: ContextMut<'_, EmEnv>, clk_id: clockid_t, tp: c_int) 0 } -pub fn _clock_settime(mut _ctx: ContextMut<'_, EmEnv>, _clk_id: i32, _tp: i32) -> i32 { +pub fn _clock_settime(mut _ctx: FunctionEnvMut, _clk_id: i32, _tp: i32) -> i32 { debug!("emscripten::_clock_settime"); // clock_settime(clk_id, tp) 0 } /// emscripten: ___clock_gettime -pub fn ___clock_gettime(ctx: ContextMut<'_, EmEnv>, clk_id: clockid_t, tp: c_int) -> c_int { +pub fn ___clock_gettime(ctx: FunctionEnvMut, clk_id: clockid_t, tp: c_int) -> c_int { debug!("emscripten::___clock_gettime {} {}", clk_id, tp); _clock_gettime(ctx, clk_id, tp) } /// emscripten: _clock -pub fn _clock(mut _ctx: ContextMut<'_, EmEnv>) -> c_int { +pub fn _clock(mut _ctx: FunctionEnvMut) -> c_int { debug!("emscripten::_clock"); 0 // TODO: unimplemented } /// emscripten: _difftime -pub fn _difftime(mut _ctx: ContextMut<'_, EmEnv>, t0: u32, t1: u32) -> f64 { +pub fn _difftime(mut _ctx: FunctionEnvMut, t0: u32, t1: u32) -> f64 { debug!("emscripten::_difftime"); (t0 - t1) as _ } -pub fn _gmtime_r(mut _ctx: ContextMut<'_, EmEnv>, _one: i32, _two: i32) -> i32 { +pub fn _gmtime_r(mut _ctx: FunctionEnvMut, _one: i32, _two: i32) -> i32 { debug!("emscripten::_gmtime_r"); -1 } -pub fn _mktime(mut _ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _mktime(mut _ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_mktime"); -1 } -pub fn _gmtime(mut _ctx: ContextMut<'_, EmEnv>, _one: i32) -> i32 { +pub fn _gmtime(mut _ctx: FunctionEnvMut, _one: i32) -> i32 { debug!("emscripten::_gmtime"); -1 } @@ -171,13 +171,13 @@ struct guest_tm { } /// emscripten: _tvset -pub fn _tvset(mut _ctx: ContextMut<'_, EmEnv>) { +pub fn _tvset(mut _ctx: FunctionEnvMut) { debug!("emscripten::_tvset UNIMPLEMENTED"); } /// formats time as a C string #[allow(clippy::cast_ptr_alignment)] -unsafe fn fmt_time(ctx: ContextMut<'_, EmEnv>, time: u32) -> *const c_char { +unsafe fn fmt_time(ctx: FunctionEnvMut, time: u32) -> *const c_char { let date = &*(emscripten_memory_pointer!(ctx, ctx.data().memory(0), time) as *mut guest_tm); let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; @@ -202,12 +202,12 @@ unsafe fn fmt_time(ctx: ContextMut<'_, EmEnv>, time: u32) -> *const c_char { } /// emscripten: _asctime -pub fn _asctime(mut ctx: ContextMut<'_, EmEnv>, time: u32) -> u32 { +pub fn _asctime(mut ctx: FunctionEnvMut, time: u32) -> u32 { debug!("emscripten::_asctime {}", time); unsafe { - let time_str_ptr = fmt_time(ctx.as_context_mut(), time); - copy_cstr_into_wasm(ctx, time_str_ptr) + let time_str_ptr = fmt_time(ctx.as_mut(), time); + copy_cstr_into_wasm(&mut ctx, time_str_ptr) // let c_str = emscripten_memory_pointer!(ctx, ctx.data().memory(0), res) as *mut i8; // use std::ffi::CStr; @@ -216,7 +216,7 @@ pub fn _asctime(mut ctx: ContextMut<'_, EmEnv>, time: u32) -> u32 { } /// emscripten: _asctime_r -pub fn _asctime_r(mut ctx: ContextMut<'_, EmEnv>, time: u32, buf: u32) -> u32 { +pub fn _asctime_r(mut ctx: FunctionEnvMut, time: u32, buf: u32) -> u32 { debug!("emscripten::_asctime_r {}, {}", time, buf); unsafe { @@ -224,7 +224,7 @@ pub fn _asctime_r(mut ctx: ContextMut<'_, EmEnv>, time: u32, buf: u32) -> u32 { // to write out more than 26 bytes (including the null terminator). // See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html // Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator. - let time_str_ptr = fmt_time(ctx.as_context_mut(), time); + let time_str_ptr = fmt_time(ctx.as_mut(), time); write_to_buf(ctx, time_str_ptr, buf, 26) // let c_str = emscripten_memory_pointer!(ctx, ctx.data().memory(0), res) as *mut i8; @@ -235,7 +235,7 @@ pub fn _asctime_r(mut ctx: ContextMut<'_, EmEnv>, time: u32, buf: u32) -> u32 { /// emscripten: _localtime #[allow(clippy::cast_ptr_alignment)] -pub fn _localtime(mut ctx: ContextMut<'_, EmEnv>, time_p: u32) -> c_int { +pub fn _localtime(mut ctx: FunctionEnvMut, time_p: u32) -> c_int { debug!("emscripten::_localtime {}", time_p); // NOTE: emscripten seems to want tzset() called in this function // https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r @@ -247,8 +247,7 @@ pub fn _localtime(mut ctx: ContextMut<'_, EmEnv>, time_p: u32) -> c_int { }; unsafe { - let tm_struct_offset = - env::call_malloc(ctx.as_context_mut(), mem::size_of::() as _); + let tm_struct_offset = env::call_malloc(&mut ctx, mem::size_of::() as _); let tm_struct_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), tm_struct_offset) as *mut guest_tm; // debug!( @@ -273,7 +272,7 @@ pub fn _localtime(mut ctx: ContextMut<'_, EmEnv>, time_p: u32) -> c_int { } /// emscripten: _localtime_r #[allow(clippy::cast_ptr_alignment)] -pub fn _localtime_r(ctx: ContextMut<'_, EmEnv>, time_p: u32, result: u32) -> c_int { +pub fn _localtime_r(ctx: FunctionEnvMut, time_p: u32, result: u32) -> c_int { debug!("emscripten::_localtime_r {}", time_p); // NOTE: emscripten seems to want tzset() called in this function @@ -310,7 +309,7 @@ pub fn _localtime_r(ctx: ContextMut<'_, EmEnv>, time_p: u32, result: u32) -> c_i /// emscripten: _time #[allow(clippy::cast_ptr_alignment)] -pub fn _time(ctx: ContextMut<'_, EmEnv>, time_p: u32) -> i32 { +pub fn _time(ctx: FunctionEnvMut, time_p: u32) -> i32 { debug!("emscripten::_time {}", time_p); unsafe { @@ -319,18 +318,18 @@ pub fn _time(ctx: ContextMut<'_, EmEnv>, time_p: u32) -> i32 { } } -pub fn _ctime_r(mut ctx: ContextMut<'_, EmEnv>, time_p: u32, buf: u32) -> u32 { +pub fn _ctime_r(mut ctx: FunctionEnvMut, time_p: u32, buf: u32) -> u32 { debug!("emscripten::_ctime_r {} {}", time_p, buf); // var stack = stackSave(); let (result_offset, _result_slice): (u32, &mut [u8]) = - unsafe { allocate_on_stack(&mut ctx.as_context_mut(), 44) }; - let time = _localtime_r(ctx.as_context_mut(), time_p, result_offset) as u32; + unsafe { allocate_on_stack(&mut ctx, 44) }; + let time = _localtime_r(ctx.as_mut(), time_p, result_offset) as u32; _asctime_r(ctx, time, buf) // stackRestore(stack); } -pub fn _ctime(ctx: ContextMut<'_, EmEnv>, time_p: u32) -> u32 { +pub fn _ctime(ctx: FunctionEnvMut, time_p: u32) -> u32 { debug!("emscripten::_ctime {}", time_p); let tm_current = 2414544; _ctime_r(ctx, time_p, tm_current) @@ -339,7 +338,7 @@ pub fn _ctime(ctx: ContextMut<'_, EmEnv>, time_p: u32) -> u32 { /// emscripten: _timegm #[cfg(not(target_os = "windows"))] #[allow(clippy::cast_ptr_alignment)] -pub fn _timegm(ctx: ContextMut<'_, EmEnv>, time_ptr: u32) -> i32 { +pub fn _timegm(ctx: FunctionEnvMut, time_ptr: u32) -> i32 { debug!("emscripten::_timegm {}", time_ptr); unsafe { @@ -380,7 +379,7 @@ pub fn _timegm(ctx: ContextMut<'_, EmEnv>, time_ptr: u32) -> i32 { } #[cfg(target_os = "windows")] -pub fn _timegm(mut _ctx: ContextMut<'_, EmEnv>, _time_ptr: c_int) -> i32 { +pub fn _timegm(mut _ctx: FunctionEnvMut, _time_ptr: c_int) -> i32 { debug!( "emscripten::_timegm - UNIMPLEMENTED IN WINDOWS {}", _time_ptr @@ -390,7 +389,7 @@ pub fn _timegm(mut _ctx: ContextMut<'_, EmEnv>, _time_ptr: c_int) -> i32 { /// emscripten: _strftime pub fn _strftime( - ctx: ContextMut<'_, EmEnv>, + ctx: FunctionEnvMut, s_ptr: c_int, maxsize: u32, format_ptr: c_int, @@ -443,7 +442,7 @@ pub fn _strftime( /// emscripten: _strftime_l pub fn _strftime_l( - ctx: ContextMut<'_, EmEnv>, + ctx: FunctionEnvMut, s_ptr: c_int, maxsize: u32, format_ptr: c_int, diff --git a/lib/emscripten/src/ucontext.rs b/lib/emscripten/src/ucontext.rs index d987cb0ba1c..58c9f929bc7 100644 --- a/lib/emscripten/src/ucontext.rs +++ b/lib/emscripten/src/ucontext.rs @@ -1,12 +1,12 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; -pub fn _getcontext(mut _ctx: ContextMut<'_, EmEnv>, _ucp: i32) -> i32 { +pub fn _getcontext(mut _ctx: FunctionEnvMut, _ucp: i32) -> i32 { debug!("emscripten::_getcontext({})", _ucp); 0 } pub fn _makecontext( - mut _ctx: ContextMut<'_, EmEnv>, + mut _ctx: FunctionEnvMut, _ucp: i32, _func: i32, _argc: i32, @@ -17,11 +17,11 @@ pub fn _makecontext( _ucp, _func, _argc, _argv ); } -pub fn _setcontext(mut _ctx: ContextMut<'_, EmEnv>, _ucp: i32) -> i32 { +pub fn _setcontext(mut _ctx: FunctionEnvMut, _ucp: i32) -> i32 { debug!("emscripten::_setcontext({})", _ucp); 0 } -pub fn _swapcontext(mut _ctx: ContextMut<'_, EmEnv>, _oucp: i32, _ucp: i32) -> i32 { +pub fn _swapcontext(mut _ctx: FunctionEnvMut, _oucp: i32, _ucp: i32) -> i32 { debug!("emscripten::_swapcontext({}, {})", _oucp, _ucp); 0 } diff --git a/lib/emscripten/src/unistd.rs b/lib/emscripten/src/unistd.rs index 7a6090199bd..b6875d055ab 100644 --- a/lib/emscripten/src/unistd.rs +++ b/lib/emscripten/src/unistd.rs @@ -1,7 +1,7 @@ use crate::EmEnv; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; -pub fn confstr(mut _ctx: ContextMut<'_, EmEnv>, _name: i32, _buf_pointer: i32, _len: i32) -> i32 { +pub fn confstr(mut _ctx: FunctionEnvMut, _name: i32, _buf_pointer: i32, _len: i32) -> i32 { debug!("unistd::confstr({}, {}, {})", _name, _buf_pointer, _len); 0 } diff --git a/lib/emscripten/src/utils.rs b/lib/emscripten/src/utils.rs index 303c277fa87..b645ae00ea8 100644 --- a/lib/emscripten/src/utils.rs +++ b/lib/emscripten/src/utils.rs @@ -8,7 +8,7 @@ use std::mem::size_of; use std::os::raw::c_char; use std::path::PathBuf; use std::slice; -use wasmer::{AsContextMut, ContextMut, GlobalInit, Memory, Module, Pages, WasmPtr}; +use wasmer::{FunctionEnvMut, GlobalInit, Memory, Module, Pages, WasmPtr}; /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { @@ -94,7 +94,7 @@ pub fn get_emscripten_metadata(module: &Module) -> Result, St } pub unsafe fn write_to_buf( - ctx: ContextMut<'_, EmEnv>, + ctx: FunctionEnvMut, string: *const c_char, buf: u32, max: u32, @@ -109,10 +109,10 @@ pub unsafe fn write_to_buf( } /// This function expects nullbyte to be appended. -pub unsafe fn copy_cstr_into_wasm(mut ctx: ContextMut<'_, EmEnv>, cstr: *const c_char) -> u32 { +pub unsafe fn copy_cstr_into_wasm(ctx: &mut FunctionEnvMut, cstr: *const c_char) -> u32 { let s = CStr::from_ptr(cstr).to_str().unwrap(); let cstr_len = s.len(); - let space_offset = env::call_malloc(ctx.as_context_mut(), (cstr_len as u32) + 1); + let space_offset = env::call_malloc(ctx, (cstr_len as u32) + 1); let raw_memory = emscripten_memory_pointer!(ctx, ctx.data().memory(0), space_offset) as *mut c_char; let slice = slice::from_raw_parts_mut(raw_memory, cstr_len); @@ -131,12 +131,12 @@ pub unsafe fn copy_cstr_into_wasm(mut ctx: ContextMut<'_, EmEnv>, cstr: *const c /// # Safety /// This method is unsafe because it operates directly with the slice of memory represented by the address pub unsafe fn allocate_on_stack<'a, T: Copy>( - ctx: &mut ContextMut<'a, EmEnv>, + mut ctx: &mut FunctionEnvMut<'a, EmEnv>, count: u32, ) -> (u32, &'a mut [T]) { let stack_alloc_ref = get_emscripten_funcs(ctx).stack_alloc_ref().unwrap().clone(); let offset = stack_alloc_ref - .call(&mut ctx.as_context_mut(), count * (size_of::() as u32)) + .call(&mut ctx, count * (size_of::() as u32)) .unwrap(); let addr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), offset) as *mut T; @@ -148,7 +148,7 @@ pub unsafe fn allocate_on_stack<'a, T: Copy>( /// # Safety /// This method is unsafe because it uses `allocate_on_stack` which is unsafe pub unsafe fn allocate_cstr_on_stack<'a>( - ctx: &'a mut ContextMut<'a, EmEnv>, + ctx: &'a mut FunctionEnvMut<'a, EmEnv>, s: &str, ) -> (u32, &'a [u8]) { let (offset, slice) = allocate_on_stack(ctx, (s.len() + 1) as u32); @@ -163,7 +163,7 @@ pub unsafe fn allocate_cstr_on_stack<'a>( #[cfg(not(target_os = "windows"))] pub unsafe fn copy_terminated_array_of_cstrs( - mut _ctx: ContextMut<'_, EmEnv>, + mut _ctx: FunctionEnvMut, cstrs: *mut *mut c_char, ) -> u32 { let _total_num = { @@ -203,7 +203,7 @@ pub struct GuestStat { } #[allow(clippy::cast_ptr_alignment)] -pub unsafe fn copy_stat_into_wasm(ctx: ContextMut<'_, EmEnv>, buf: u32, stat: &stat) { +pub unsafe fn copy_stat_into_wasm(ctx: FunctionEnvMut, buf: u32, stat: &stat) { let stat_ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), buf) as *mut GuestStat; (*stat_ptr).st_dev = stat.st_dev as _; (*stat_ptr).__st_dev_padding = 0; @@ -231,7 +231,7 @@ pub unsafe fn copy_stat_into_wasm(ctx: ContextMut<'_, EmEnv>, buf: u32, stat: &s } #[allow(dead_code)] // it's used in `env/windows/mod.rs`. -pub fn read_string_from_wasm(ctx: ContextMut<'_, EmEnv>, memory: &Memory, offset: u32) -> String { +pub fn read_string_from_wasm(ctx: FunctionEnvMut, memory: &Memory, offset: u32) -> String { WasmPtr::::new(offset) .read_utf8_string_with_nul(&ctx, memory) .unwrap() @@ -239,7 +239,7 @@ pub fn read_string_from_wasm(ctx: ContextMut<'_, EmEnv>, memory: &Memory, offset /// This function trys to find an entry in mapdir /// translating paths into their correct value -pub fn get_cstr_path(ctx: ContextMut<'_, EmEnv>, path: *const i8) -> Option { +pub fn get_cstr_path(ctx: FunctionEnvMut, path: *const i8) -> Option { use std::collections::VecDeque; let path_str = @@ -277,7 +277,7 @@ pub fn get_cstr_path(ctx: ContextMut<'_, EmEnv>, path: *const i8) -> Option) -> Option { +pub fn get_current_directory(ctx: FunctionEnvMut) -> Option { if let Some(val) = get_emscripten_data(&ctx) .as_ref() .unwrap() diff --git a/lib/emscripten/src/varargs.rs b/lib/emscripten/src/varargs.rs index 826dc15cf9b..ab5dcf453b2 100644 --- a/lib/emscripten/src/varargs.rs +++ b/lib/emscripten/src/varargs.rs @@ -3,7 +3,7 @@ use std::mem; use wasmer::FromToNativeWasmType; // use std::ffi::CStr; use std::os::raw::c_char; -use wasmer::ContextMut; +use wasmer::FunctionEnvMut; #[repr(transparent)] #[derive(Copy, Clone)] @@ -12,14 +12,14 @@ pub struct VarArgs { } impl VarArgs { - pub fn get(&mut self, ctx: &ContextMut<'_, EmEnv>) -> T { + pub fn get(&mut self, ctx: &FunctionEnvMut) -> T { let ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), self.pointer); self.pointer += mem::size_of::() as u32; unsafe { (ptr as *const T).read() } } // pub fn getStr<'a>(&mut self, ctx: &mut Ctx) -> &'a CStr { - pub fn get_str(&mut self, ctx: &ContextMut<'_, EmEnv>) -> *const c_char { + pub fn get_str(&mut self, ctx: &FunctionEnvMut) -> *const c_char { let ptr_addr: u32 = self.get(ctx); let ptr = emscripten_memory_pointer!(ctx, ctx.data().memory(0), ptr_addr) as *const c_char; ptr diff --git a/lib/middlewares/src/metering.rs b/lib/middlewares/src/metering.rs index 8c9d12a107d..7c287e8d10d 100644 --- a/lib/middlewares/src/metering.rs +++ b/lib/middlewares/src/metering.rs @@ -13,7 +13,7 @@ use std::fmt; use std::sync::{Arc, Mutex}; use wasmer::wasmparser::{Operator, Type as WpType, TypeOrFuncType as WpTypeOrFuncType}; use wasmer::{ - AsContextMut, ExportIndex, FunctionMiddleware, GlobalInit, GlobalType, Instance, + AsStoreMut, ExportIndex, FunctionMiddleware, GlobalInit, GlobalType, Instance, LocalFunctionIndex, MiddlewareError, MiddlewareReaderState, ModuleMiddleware, Mutability, Type, }; use wasmer_types::{GlobalIndex, ModuleInfo}; @@ -273,16 +273,16 @@ impl u64 + Send + Sync> FunctionMiddleware for FunctionMeter /// /// ```rust /// use wasmer::Instance; -/// use wasmer::AsContextMut; +/// use wasmer::AsStoreMut; /// use wasmer_middlewares::metering::{get_remaining_points, MeteringPoints}; /// /// /// Check whether the instance can continue to run based on the /// /// number of remaining points. -/// fn can_continue_to_run(ctx: &mut impl AsContextMut, instance: &Instance) -> bool { -/// matches!(get_remaining_points(&mut ctx.as_context_mut(), instance), MeteringPoints::Remaining(points) if points > 0) +/// fn can_continue_to_run(store: &mut impl AsStoreMut, instance: &Instance) -> bool { +/// matches!(get_remaining_points(store, instance), MeteringPoints::Remaining(points) if points > 0) /// } /// ``` -pub fn get_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance) -> MeteringPoints { +pub fn get_remaining_points(ctx: &mut impl AsStoreMut, instance: &Instance) -> MeteringPoints { let exhausted: i32 = instance .exports .get_global("wasmer_metering_points_exhausted") @@ -321,18 +321,18 @@ pub fn get_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance) -> /// # Example /// /// ```rust -/// use wasmer::{AsContextMut, Instance}; +/// use wasmer::{AsStoreMut, Instance}; /// use wasmer_middlewares::metering::set_remaining_points; /// -/// fn update_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance) { +/// fn update_remaining_points(store: &mut impl AsStoreMut, instance: &Instance) { /// // The new limit. /// let new_limit = 10; /// /// // Update the remaining points to the `new_limit`. -/// set_remaining_points(&mut ctx.as_context_mut(), instance, new_limit); +/// set_remaining_points(store, instance, new_limit); /// } /// ``` -pub fn set_remaining_points(ctx: &mut impl AsContextMut, instance: &Instance, points: u64) { +pub fn set_remaining_points(ctx: &mut impl AsStoreMut, instance: &Instance, points: u64) { instance .exports .get_global("wasmer_metering_remaining_points") @@ -354,8 +354,7 @@ mod tests { use std::sync::Arc; use wasmer::{ - imports, wat2wasm, CompilerConfig, Context, Cranelift, Module, Store, TypedFunction, - Universal, + imports, wat2wasm, CompilerConfig, Cranelift, Module, Store, TypedFunction, Universal, }; fn cost_function(operator: &Operator) -> u64 { @@ -384,18 +383,16 @@ mod tests { #[test] fn get_remaining_points_works() { - use wasmer::Context as WasmerContext; let metering = Arc::new(Metering::new(10, cost_function)); let mut compiler_config = Cranelift::default(); compiler_config.push_middleware(metering); - let store = Store::new_with_engine(&Universal::new(compiler_config).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler_config).engine()); let module = Module::new(&store, bytecode()).unwrap(); - let mut ctx = Context::new(&store, ()); // Instantiate - let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); + let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); assert_eq!( - get_remaining_points(&mut ctx.as_context_mut(), &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(10) ); @@ -409,25 +406,25 @@ mod tests { .exports .get_function("add_one") .unwrap() - .native(&ctx) + .native(&store) .unwrap(); - add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); + add_one.call(&mut store, 1).unwrap(); assert_eq!( - get_remaining_points(&mut ctx.as_context_mut(), &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(6) ); // Second call - add_one.call(&mut ctx.as_context_mut(), 1).unwrap(); + add_one.call(&mut store, 1).unwrap(); assert_eq!( - get_remaining_points(&mut ctx.as_context_mut(), &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(2) ); // Third call fails due to limit - assert!(add_one.call(&mut ctx.as_context_mut(), 1).is_err()); + assert!(add_one.call(&mut store, 1).is_err()); assert_eq!( - get_remaining_points(&mut ctx.as_context_mut(), &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Exhausted ); } @@ -437,55 +434,54 @@ mod tests { let metering = Arc::new(Metering::new(10, cost_function)); let mut compiler_config = Cranelift::default(); compiler_config.push_middleware(metering); - let store = Store::new_with_engine(&Universal::new(compiler_config).engine()); + let mut store = Store::new_with_engine(&Universal::new(compiler_config).engine()); let module = Module::new(&store, bytecode()).unwrap(); - let mut ctx = Context::new(module.store(), ()); // Instantiate - let instance = Instance::new(&mut ctx, &module, &imports! {}).unwrap(); + let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); assert_eq!( - get_remaining_points(&mut ctx, &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(10) ); let add_one: TypedFunction = instance .exports .get_function("add_one") .unwrap() - .native(&ctx) + .native(&store) .unwrap(); // Increase a bit to have enough for 3 calls - set_remaining_points(&mut ctx, &instance, 12); + set_remaining_points(&mut store, &instance, 12); // Ensure we can use the new points now - add_one.call(&mut &mut ctx, 1).unwrap(); + add_one.call(&mut store, 1).unwrap(); assert_eq!( - get_remaining_points(&mut ctx, &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(8) ); - add_one.call(&mut &mut ctx, 1).unwrap(); + add_one.call(&mut store, 1).unwrap(); assert_eq!( - get_remaining_points(&mut ctx, &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(4) ); - add_one.call(&mut &mut ctx, 1).unwrap(); + add_one.call(&mut store, 1).unwrap(); assert_eq!( - get_remaining_points(&mut ctx, &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(0) ); - assert!(add_one.call(&mut &mut ctx, 1).is_err()); + assert!(add_one.call(&mut store, 1).is_err()); assert_eq!( - get_remaining_points(&mut ctx, &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Exhausted ); // Add some points for another call - set_remaining_points(&mut ctx, &instance, 4); + set_remaining_points(&mut store, &instance, 4); assert_eq!( - get_remaining_points(&mut ctx, &instance), + get_remaining_points(&mut store, &instance), MeteringPoints::Remaining(4) ); } diff --git a/lib/vm/src/export.rs b/lib/vm/src/export.rs index b87581cbd7f..68427062f7c 100644 --- a/lib/vm/src/export.rs +++ b/lib/vm/src/export.rs @@ -1,9 +1,9 @@ // This file contains code from external sources. // Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md -use crate::context::InternalContextHandle; use crate::global::VMGlobal; use crate::memory::VMMemory; +use crate::store::InternalStoreHandle; use crate::table::VMTable; use crate::vmcontext::VMFunctionKind; use crate::{MaybeInstanceOwned, VMCallerCheckedAnyfunc}; @@ -13,16 +13,16 @@ use wasmer_types::FunctionType; /// The value of an export passed from one instance to another. pub enum VMExtern { /// A function export value. - Function(InternalContextHandle), + Function(InternalStoreHandle), /// A table export value. - Table(InternalContextHandle), + Table(InternalStoreHandle), /// A memory export value. - Memory(InternalContextHandle), + Memory(InternalStoreHandle), /// A global export value. - Global(InternalContextHandle), + Global(InternalStoreHandle), } /// A function export value. diff --git a/lib/vm/src/extern_ref.rs b/lib/vm/src/extern_ref.rs index 89657a00907..f99a7e93f51 100644 --- a/lib/vm/src/extern_ref.rs +++ b/lib/vm/src/extern_ref.rs @@ -2,7 +2,7 @@ use std::any::Any; use wasmer_types::RawValue; -use crate::context::InternalContextHandle; +use crate::store::InternalStoreHandle; /// Underlying object referenced by a `VMExternRef`. pub struct VMExternObj { @@ -27,7 +27,7 @@ impl VMExternObj { /// Represents an opaque reference to any data within WebAssembly. #[repr(transparent)] #[derive(Debug, Clone, Copy)] -pub struct VMExternRef(pub InternalContextHandle); +pub struct VMExternRef(pub InternalStoreHandle); impl VMExternRef { /// Converts the `VMExternRef` into a `RawValue`. @@ -42,6 +42,6 @@ impl VMExternRef { /// # Safety /// `raw` must be a valid `VMExternRef` instance. pub unsafe fn from_raw(raw: RawValue) -> Option { - InternalContextHandle::from_index(raw.externref).map(Self) + InternalStoreHandle::from_index(raw.externref).map(Self) } } diff --git a/lib/vm/src/function_env.rs b/lib/vm/src/function_env.rs new file mode 100644 index 00000000000..ccedf04385e --- /dev/null +++ b/lib/vm/src/function_env.rs @@ -0,0 +1,27 @@ +use std::any::Any; + +/// Underlying FunctionEnvironment used by a `VMFunction`. +pub struct VMFunctionEnvironment { + contents: Box, +} + +impl VMFunctionEnvironment { + /// Wraps the given value to expose it to Wasm code as a function context. + pub fn new(val: impl Any + Send + 'static) -> Self { + Self { + contents: Box::new(val), + } + } + + #[allow(clippy::should_implement_trait)] + /// Returns a reference to the underlying value. + pub fn as_ref(&self) -> &(dyn Any + Send + 'static) { + &*self.contents + } + + #[allow(clippy::should_implement_trait)] + /// Returns a mutable reference to the underlying value. + pub fn as_mut(&mut self) -> &mut (dyn Any + Send + 'static) { + &mut *self.contents + } +} diff --git a/lib/vm/src/global.rs b/lib/vm/src/global.rs index 5dd6f6665ac..682a66fb294 100644 --- a/lib/vm/src/global.rs +++ b/lib/vm/src/global.rs @@ -1,4 +1,4 @@ -use crate::{context::MaybeInstanceOwned, vmcontext::VMGlobalDefinition}; +use crate::{store::MaybeInstanceOwned, vmcontext::VMGlobalDefinition}; use std::{cell::UnsafeCell, ptr::NonNull}; use wasmer_types::GlobalType; diff --git a/lib/vm/src/instance/mod.rs b/lib/vm/src/instance/mod.rs index 43d843fedd6..0fefd60a651 100644 --- a/lib/vm/src/instance/mod.rs +++ b/lib/vm/src/instance/mod.rs @@ -8,18 +8,18 @@ mod allocator; -use crate::context::{ContextObjects, InternalContextHandle}; use crate::export::VMExtern; use crate::imports::Imports; use crate::memory::MemoryError; +use crate::store::{InternalStoreHandle, StoreObjects}; use crate::table::TableElement; -use crate::trap::{catch_traps, Trap, TrapCode, TrapHandler}; +use crate::trap::{catch_traps, Trap, TrapCode}; use crate::vmcontext::{ - VMBuiltinFunctionsArray, VMCallerCheckedAnyfunc, VMContext, VMFunctionEnvironment, + VMBuiltinFunctionsArray, VMCallerCheckedAnyfunc, VMContext, VMFunctionContext, VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMTrampoline, }; -use crate::{FunctionBodyPtr, MaybeInstanceOwned, VMFunctionBody}; +use crate::{FunctionBodyPtr, MaybeInstanceOwned, TrapHandlerFn, VMFunctionBody}; use crate::{VMFuncRef, VMFunction, VMGlobal, VMMemory, VMTable}; pub use allocator::InstanceAllocator; use memoffset::offset_of; @@ -52,19 +52,19 @@ pub(crate) struct Instance { module: Arc, /// Pointer to the object store of the context owning this instance. - context: *mut ContextObjects, + context: *mut StoreObjects, /// Offsets in the `vmctx` region. offsets: VMOffsets, /// WebAssembly linear memory data. - memories: BoxedSlice>, + memories: BoxedSlice>, /// WebAssembly table data. - tables: BoxedSlice>, + tables: BoxedSlice>, /// WebAssembly global data. - globals: BoxedSlice>, + globals: BoxedSlice>, /// Pointers to functions in executable memory. functions: BoxedSlice, @@ -119,11 +119,11 @@ impl Instance { &*self.module } - fn context(&self) -> &ContextObjects { + fn context(&self) -> &StoreObjects { unsafe { &*self.context } } - fn context_mut(&mut self) -> &mut ContextObjects { + fn context_mut(&mut self) -> &mut StoreObjects { unsafe { &mut *self.context } } @@ -283,7 +283,7 @@ impl Instance { /// Invoke the WebAssembly start function of the instance, if one is present. fn invoke_start_function( &self, - trap_handler: &(dyn TrapHandler + 'static), + trap_handler: Option<*const TrapHandlerFn<'static>>, ) -> Result<(), Trap> { let start_index = match self.module.start_function { Some(idx) => idx, @@ -299,7 +299,7 @@ impl Instance { .0; ( body as *const _, - VMFunctionEnvironment { + VMFunctionContext { vmctx: self.vmctx_ptr(), }, ) @@ -314,7 +314,7 @@ impl Instance { // Make the call. unsafe { catch_traps(trap_handler, || { - mem::transmute::<*const VMFunctionBody, unsafe extern "C" fn(VMFunctionEnvironment)>( + mem::transmute::<*const VMFunctionBody, unsafe extern "C" fn(VMFunctionContext)>( callee_address, )(callee_vmctx) }) @@ -760,7 +760,7 @@ impl Instance { pub(crate) fn get_table_handle( &mut self, table_index: TableIndex, - ) -> InternalContextHandle { + ) -> InternalStoreHandle { if let Some(local_table_index) = self.module.local_table_index(table_index) { self.tables[local_table_index] } else { @@ -816,12 +816,12 @@ impl InstanceHandle { pub unsafe fn new( allocator: InstanceAllocator, module: Arc, - context: &mut ContextObjects, + context: &mut StoreObjects, finished_functions: BoxedSlice, finished_function_call_trampolines: BoxedSlice, - finished_memories: BoxedSlice>, - finished_tables: BoxedSlice>, - finished_globals: BoxedSlice>, + finished_memories: BoxedSlice>, + finished_tables: BoxedSlice>, + finished_globals: BoxedSlice>, imports: Imports, vmshared_signatures: BoxedSlice, ) -> Result { @@ -938,7 +938,7 @@ impl InstanceHandle { /// Only safe to call immediately after instantiation. pub unsafe fn finish_instantiation( &mut self, - trap_handler: &(dyn TrapHandler + 'static), + trap_handler: Option<*const TrapHandlerFn<'static>>, data_initializers: &[DataInitializer<'_>], ) -> Result<(), Trap> { let instance = self.instance_mut(); @@ -1010,7 +1010,7 @@ impl InstanceHandle { kind: VMFunctionKind::Static, host_data: Box::new(()), }; - InternalContextHandle::new(self.instance_mut().context_mut(), vm_function) + InternalStoreHandle::new(self.instance_mut().context_mut(), vm_function) } else { let import = instance.imported_function(index); import.handle @@ -1290,7 +1290,7 @@ fn initialize_globals(instance: &Instance) { /// future funcref operations are just looking up this data. fn build_funcrefs( module_info: &ModuleInfo, - ctx: &ContextObjects, + ctx: &StoreObjects, imports: &Imports, finished_functions: &BoxedSlice, vmshared_signatures: &BoxedSlice, @@ -1318,7 +1318,7 @@ fn build_funcrefs( let anyfunc = VMCallerCheckedAnyfunc { func_ptr: func_ptr.0, type_index, - vmctx: VMFunctionEnvironment { vmctx: vmctx_ptr }, + vmctx: VMFunctionContext { vmctx: vmctx_ptr }, call_trampoline, }; func_refs.push(anyfunc); diff --git a/lib/vm/src/lib.rs b/lib/vm/src/lib.rs index 835b27bdd29..1b30f1e61e4 100644 --- a/lib/vm/src/lib.rs +++ b/lib/vm/src/lib.rs @@ -20,9 +20,9 @@ ) )] -mod context; mod export; mod extern_ref; +mod function_env; mod global; mod imports; mod instance; @@ -30,6 +30,7 @@ mod memory; mod mmap; mod probestack; mod sig_registry; +mod store; mod table; mod trap; mod vmcontext; @@ -38,11 +39,9 @@ pub mod libcalls; use std::ptr::NonNull; -pub use crate::context::{ - ContextHandle, ContextId, ContextObjects, InternalContextHandle, MaybeInstanceOwned, -}; pub use crate::export::*; pub use crate::extern_ref::{VMExternObj, VMExternRef}; +pub use crate::function_env::VMFunctionEnvironment; pub use crate::global::*; pub use crate::imports::Imports; pub use crate::instance::{InstanceAllocator, InstanceHandle}; @@ -50,10 +49,13 @@ pub use crate::memory::{MemoryError, VMMemory}; pub use crate::mmap::Mmap; pub use crate::probestack::PROBESTACK; pub use crate::sig_registry::SignatureRegistry; +pub use crate::store::{ + InternalStoreHandle, MaybeInstanceOwned, StoreHandle, StoreId, StoreObjects, +}; pub use crate::table::{TableElement, VMTable}; pub use crate::trap::*; pub use crate::vmcontext::{ - VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionEnvironment, + VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionContext, VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMTrampoline, }; diff --git a/lib/vm/src/memory.rs b/lib/vm/src/memory.rs index 52afdb90b04..098dd8501b6 100644 --- a/lib/vm/src/memory.rs +++ b/lib/vm/src/memory.rs @@ -6,7 +6,7 @@ //! `Memory` is to WebAssembly linear memories what `Table` is to WebAssembly tables. use crate::vmcontext::VMMemoryDefinition; -use crate::{context::MaybeInstanceOwned, mmap::Mmap}; +use crate::{mmap::Mmap, store::MaybeInstanceOwned}; use more_asserts::assert_ge; use std::cell::UnsafeCell; use std::convert::TryInto; diff --git a/lib/vm/src/context.rs b/lib/vm/src/store.rs similarity index 69% rename from lib/vm/src/context.rs rename to lib/vm/src/store.rs index 1b8ca708ab7..747154f9d50 100644 --- a/lib/vm/src/context.rs +++ b/lib/vm/src/store.rs @@ -9,7 +9,7 @@ use std::{ use crate::VMExternObj; -use crate::{InstanceHandle, VMFunction, VMGlobal, VMMemory, VMTable}; +use crate::{InstanceHandle, VMFunction, VMFunctionEnvironment, VMGlobal, VMMemory, VMTable}; /// Unique ID to identify a context. /// @@ -17,9 +17,9 @@ use crate::{InstanceHandle, VMFunction, VMGlobal, VMMemory, VMTable}; /// context. This is used to check that a handle is always used with the /// correct context. #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct ContextId(NonZeroU64); +pub struct StoreId(NonZeroU64); -impl Default for ContextId { +impl Default for StoreId { // Allocates a unique ID for a new context. fn default() -> Self { // No overflow checking is needed here: overflowing this would take @@ -31,18 +31,18 @@ impl Default for ContextId { /// Trait to represent an object managed by a context. This is implemented on /// the VM types managed by the context. -pub trait ContextObject: Sized { - fn list(ctx: &ContextObjects) -> &Vec; - fn list_mut(ctx: &mut ContextObjects) -> &mut Vec; +pub trait StoreObject: Sized { + fn list(ctx: &StoreObjects) -> &Vec; + fn list_mut(ctx: &mut StoreObjects) -> &mut Vec; } macro_rules! impl_context_object { ($($field:ident => $ty:ty,)*) => { $( - impl ContextObject for $ty { - fn list(ctx: &ContextObjects) -> &Vec { + impl StoreObject for $ty { + fn list(ctx: &StoreObjects) -> &Vec { &ctx.$field } - fn list_mut(ctx: &mut ContextObjects) -> &mut Vec { + fn list_mut(ctx: &mut StoreObjects) -> &mut Vec { &mut ctx.$field } } @@ -56,33 +56,35 @@ impl_context_object! { instances => InstanceHandle, memories => VMMemory, extern_objs => VMExternObj, + function_environments => VMFunctionEnvironment, } /// Set of objects managed by a context. #[derive(Default)] -pub struct ContextObjects { - id: ContextId, +pub struct StoreObjects { + id: StoreId, memories: Vec, tables: Vec, globals: Vec, functions: Vec, instances: Vec, extern_objs: Vec, + function_environments: Vec, } -impl ContextObjects { +impl StoreObjects { /// Returns the ID of this context. - pub fn id(&self) -> ContextId { + pub fn id(&self) -> StoreId { self.id } /// Returns a pair of mutable references from two handles. /// /// Panics if both handles point to the same object. - pub fn get_2_mut( + pub fn get_2_mut( &mut self, - a: InternalContextHandle, - b: InternalContextHandle, + a: InternalStoreHandle, + b: InternalStoreHandle, ) -> (&mut T, &mut T) { assert_ne!(a.index(), b.index()); let list = T::list_mut(self); @@ -100,12 +102,12 @@ impl ContextObjects { /// /// Internally this is just an integer index into a context. A reference to the /// context must be passed in separately to access the actual object. -pub struct ContextHandle { - id: ContextId, - internal: InternalContextHandle, +pub struct StoreHandle { + id: StoreId, + internal: InternalStoreHandle, } -impl Clone for ContextHandle { +impl Clone for StoreHandle { fn clone(&self) -> Self { Self { id: self.id, @@ -114,98 +116,98 @@ impl Clone for ContextHandle { } } -impl fmt::Debug for ContextHandle { +impl fmt::Debug for StoreHandle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ContextHandle") + f.debug_struct("StoreHandle") .field("id", &self.id) .field("internal", &self.internal.index()) .finish() } } -impl PartialEq for ContextHandle { +impl PartialEq for StoreHandle { fn eq(&self, other: &Self) -> bool { self.id == other.id && self.internal == other.internal } } -impl Eq for ContextHandle {} +impl Eq for StoreHandle {} -impl ContextHandle { +impl StoreHandle { /// Moves the given object into a context and returns a handle to it. - pub fn new(ctx: &mut ContextObjects, val: T) -> Self { + pub fn new(ctx: &mut StoreObjects, val: T) -> Self { Self { id: ctx.id, - internal: InternalContextHandle::new(ctx, val), + internal: InternalStoreHandle::new(ctx, val), } } /// Returns a reference to the object that this handle points to. - pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { + pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T { assert_eq!(self.id, ctx.id, "object used with the wrong context"); self.internal.get(ctx) } /// Returns a mutable reference to the object that this handle points to. - pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { + pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T { assert_eq!(self.id, ctx.id, "object used with the wrong context"); self.internal.get_mut(ctx) } /// Returns the internal handle contains within this handle. - pub fn internal_handle(&self) -> InternalContextHandle { + pub fn internal_handle(&self) -> InternalStoreHandle { self.internal } /// Returns the ID of the context associated with the handle. - pub fn context_id(&self) -> ContextId { + pub fn store_id(&self) -> StoreId { self.id } - /// Constructs a `ContextHandle` from a `ContextId` and an `InternalContextHandle`. + /// Constructs a `StoreHandle` from a `StoreId` and an `InternalStoreHandle`. /// /// # Safety - /// Handling `InternalContextHandle` values is unsafe because they do not track context ID. - pub unsafe fn from_internal(id: ContextId, internal: InternalContextHandle) -> Self { + /// Handling `InternalStoreHandle` values is unsafe because they do not track context ID. + pub unsafe fn from_internal(id: StoreId, internal: InternalStoreHandle) -> Self { Self { id, internal } } } /// Internal handle to an object owned by the current context. /// -/// Unlike `ContextHandle` this does not track the context ID: it is only +/// Unlike `StoreHandle` this does not track the context ID: it is only /// intended to be used within objects already owned by a context. #[repr(transparent)] -pub struct InternalContextHandle { - // Use a NonZero here to reduce the size of Option. +pub struct InternalStoreHandle { + // Use a NonZero here to reduce the size of Option. idx: NonZeroUsize, marker: PhantomData T>, } -impl Clone for InternalContextHandle { +impl Clone for InternalStoreHandle { fn clone(&self) -> Self { *self } } -impl Copy for InternalContextHandle {} +impl Copy for InternalStoreHandle {} -impl fmt::Debug for InternalContextHandle { +impl fmt::Debug for InternalStoreHandle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("InternalContextHandle") + f.debug_struct("InternalStoreHandle") .field("idx", &self.idx) .finish() } } -impl PartialEq for InternalContextHandle { +impl PartialEq for InternalStoreHandle { fn eq(&self, other: &Self) -> bool { self.idx == other.idx } } -impl Eq for InternalContextHandle {} +impl Eq for InternalStoreHandle {} -impl InternalContextHandle { +impl InternalStoreHandle { /// Moves the given object into a context and returns a handle to it. - pub fn new(ctx: &mut ContextObjects, val: T) -> Self { + pub fn new(ctx: &mut StoreObjects, val: T) -> Self { let list = T::list_mut(ctx); let idx = NonZeroUsize::new(list.len() + 1).unwrap(); list.push(val); @@ -216,12 +218,12 @@ impl InternalContextHandle { } /// Returns a reference to the object that this handle points to. - pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T { + pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T { &T::list(ctx)[self.idx.get() - 1] } /// Returns a mutable reference to the object that this handle points to. - pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T { + pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T { &mut T::list_mut(ctx)[self.idx.get() - 1] } diff --git a/lib/vm/src/table.rs b/lib/vm/src/table.rs index 364a81f11ff..bdc5e5fdbaa 100644 --- a/lib/vm/src/table.rs +++ b/lib/vm/src/table.rs @@ -5,7 +5,7 @@ //! //! `Table` is to WebAssembly tables what `Memory` is to WebAssembly linear memories. -use crate::context::MaybeInstanceOwned; +use crate::store::MaybeInstanceOwned; use crate::vmcontext::VMTableDefinition; use crate::Trap; use crate::VMExternRef; diff --git a/lib/vm/src/trap/traphandlers.rs b/lib/vm/src/trap/traphandlers.rs index 97e564d2cf8..fc8af76fcfc 100644 --- a/lib/vm/src/trap/traphandlers.rs +++ b/lib/vm/src/trap/traphandlers.rs @@ -4,7 +4,7 @@ //! WebAssembly trap handling, which is built on top of the lower-level //! signalhandling mechanisms. -use crate::vmcontext::{VMFunctionEnvironment, VMTrampoline}; +use crate::vmcontext::{VMFunctionContext, VMTrampoline}; use crate::{Trap, VMFunctionBody}; use backtrace::Backtrace; use core::ptr::{read, read_unaligned}; @@ -32,10 +32,10 @@ static MAGIC: u8 = 0xc0; cfg_if::cfg_if! { if #[cfg(unix)] { /// Function which may handle custom signals while processing traps. - pub type TrapHandlerFn = dyn Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool; + pub type TrapHandlerFn<'a> = dyn Fn(libc::c_int, *const libc::siginfo_t, *const libc::c_void) -> bool + Send + Sync + 'a; } else if #[cfg(target_os = "windows")] { /// Function which may handle custom signals while processing traps. - pub type TrapHandlerFn = dyn Fn(winapi::um::winnt::PEXCEPTION_POINTERS) -> bool; + pub type TrapHandlerFn<'a> = dyn Fn(winapi::um::winnt::PEXCEPTION_POINTERS) -> bool + Send + Sync + 'a; } } @@ -611,14 +611,14 @@ pub unsafe fn resume_panic(payload: Box) -> ! { /// Wildly unsafe because it calls raw function pointers and reads/writes raw /// function pointers. pub unsafe fn wasmer_call_trampoline( - trap_handler: &(impl TrapHandler + 'static), - vmctx: VMFunctionEnvironment, + trap_handler: Option<*const TrapHandlerFn<'static>>, + vmctx: VMFunctionContext, trampoline: VMTrampoline, callee: *const VMFunctionBody, values_vec: *mut u8, ) -> Result<(), Trap> { catch_traps(trap_handler, || { - mem::transmute::<_, extern "C" fn(VMFunctionEnvironment, *const VMFunctionBody, *mut u8)>( + mem::transmute::<_, extern "C" fn(VMFunctionContext, *const VMFunctionBody, *mut u8)>( trampoline, )(vmctx, callee, values_vec); }) @@ -631,7 +631,7 @@ pub unsafe fn wasmer_call_trampoline( /// /// Highly unsafe since `closure` won't have any dtors run. pub unsafe fn catch_traps( - trap_handler: &(dyn TrapHandler + 'static), + trap_handler: Option<*const TrapHandlerFn<'static>>, closure: F, ) -> Result where @@ -669,7 +669,7 @@ struct TrapHandlerContext { Option, &mut dyn FnMut(TrapHandlerRegs), ) -> bool, - custom_trap: *const dyn TrapHandler, + custom_trap: Option<*const TrapHandlerFn<'static>>, } struct TrapHandlerContextInner { /// Information about the currently running coroutine. This is used to @@ -681,7 +681,7 @@ impl TrapHandlerContext { /// Runs the given function with a trap handler context. The previous /// trap handler context is preserved and restored afterwards. fn install( - custom_trap: &(dyn TrapHandler + 'static), + custom_trap: Option<*const TrapHandlerFn<'static>>, coro_trap_handler: CoroutineTrapHandler>, f: impl FnOnce() -> R, ) -> R { @@ -733,7 +733,7 @@ impl TrapHandlerContext { maybe_fault_address: Option, trap_code: Option, mut update_regs: impl FnMut(TrapHandlerRegs), - call_handler: impl Fn(&TrapHandlerFn) -> bool, + call_handler: impl Fn(&TrapHandlerFn<'static>) -> bool, ) -> bool { let ptr = TRAP_HANDLER.with(|ptr| ptr.load(Ordering::Relaxed)); if ptr.is_null() { @@ -743,8 +743,10 @@ impl TrapHandlerContext { let ctx = &*ptr; // Check if this trap is handled by a custom trap handler. - if (*ctx.custom_trap).custom_trap_handler(&call_handler) { - return true; + if let Some(trap_handler) = ctx.custom_trap { + if call_handler(&*trap_handler) { + return true; + } } (ctx.handle_trap)( @@ -855,7 +857,7 @@ unsafe fn unwind_with(reason: UnwindReason) -> ! { /// bounded. Stack overflows and other traps can be caught and execution /// returned to the root of the stack. fn on_wasm_stack T, T>( - trap_handler: &(dyn TrapHandler + 'static), + trap_handler: Option<*const TrapHandlerFn<'static>>, f: F, ) -> Result { // Allocating a new stack is pretty expensive since it involves several diff --git a/lib/vm/src/vmcontext.rs b/lib/vm/src/vmcontext.rs index 158e6ca5913..edc3bf4d40e 100644 --- a/lib/vm/src/vmcontext.rs +++ b/lib/vm/src/vmcontext.rs @@ -4,10 +4,10 @@ //! This file declares `VMContext` and several related structs which contain //! fields that compiled wasm code accesses directly. -use crate::context::InternalContextHandle; use crate::global::VMGlobal; use crate::instance::Instance; use crate::memory::VMMemory; +use crate::store::InternalStoreHandle; use crate::trap::{Trap, TrapCode}; use crate::VMFunctionBody; use crate::VMTable; @@ -22,35 +22,35 @@ use wasmer_types::RawValue; /// It may either be a pointer to the [`VMContext`] if it's a Wasm function /// or a pointer to arbitrary data controlled by the host if it's a host function. #[derive(Copy, Clone, Eq)] -pub union VMFunctionEnvironment { +pub union VMFunctionContext { /// Wasm functions take a pointer to [`VMContext`]. pub vmctx: *mut VMContext, /// Host functions can have custom environments. pub host_env: *mut std::ffi::c_void, } -impl VMFunctionEnvironment { +impl VMFunctionContext { /// Check whether the pointer stored is null or not. pub fn is_null(&self) -> bool { unsafe { self.host_env.is_null() } } } -impl std::fmt::Debug for VMFunctionEnvironment { +impl std::fmt::Debug for VMFunctionContext { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("VMFunctionEnvironment") + f.debug_struct("VMFunctionContext") .field("vmctx_or_hostenv", unsafe { &self.host_env }) .finish() } } -impl std::cmp::PartialEq for VMFunctionEnvironment { +impl std::cmp::PartialEq for VMFunctionContext { fn eq(&self, rhs: &Self) -> bool { unsafe { self.host_env as usize == rhs.host_env as usize } } } -impl std::hash::Hash for VMFunctionEnvironment { +impl std::hash::Hash for VMFunctionContext { fn hash(&self, state: &mut H) { unsafe { self.vmctx.hash(state); @@ -66,10 +66,10 @@ pub struct VMFunctionImport { pub body: *const VMFunctionBody, /// A pointer to the `VMContext` that owns the function or host env data. - pub environment: VMFunctionEnvironment, + pub environment: VMFunctionContext, /// Handle to the `VMFunction` in the context. - pub handle: InternalContextHandle, + pub handle: InternalStoreHandle, } #[cfg(test)] @@ -191,7 +191,7 @@ pub struct VMTableImport { pub definition: NonNull, /// Handle to the `VMTable` in the context. - pub handle: InternalContextHandle, + pub handle: InternalStoreHandle, } #[cfg(test)] @@ -226,7 +226,7 @@ pub struct VMMemoryImport { pub definition: NonNull, /// A handle to the `Memory` that owns the memory description. - pub handle: InternalContextHandle, + pub handle: InternalStoreHandle, } #[cfg(test)] @@ -265,7 +265,7 @@ pub struct VMGlobalImport { pub definition: NonNull, /// A handle to the `Global` that owns the global description. - pub handle: InternalContextHandle, + pub handle: InternalStoreHandle, } /// # Safety @@ -569,7 +569,7 @@ pub struct VMCallerCheckedAnyfunc { /// Function signature id. pub type_index: VMSharedSignatureIndex, /// Function `VMContext` or host env. - pub vmctx: VMFunctionEnvironment, + pub vmctx: VMFunctionContext, /// Address of the function call trampoline to invoke this function using /// a dynamic argument list. pub call_trampoline: VMTrampoline, diff --git a/lib/wasi/README.md b/lib/wasi/README.md index f2b97bb105b..86edd228817 100644 --- a/lib/wasi/README.md +++ b/lib/wasi/README.md @@ -57,7 +57,7 @@ Hello, Some("Gordon") use wasmer::{Store, Module, Instance}; use wasmer_wasi::WasiState; -let store = Store::default(); +let mut store = Store::default(); let module = Module::from_file(&store, "hello.wasm")?; // Create the `WasiEnv`. diff --git a/lib/wasi/src/lib.rs b/lib/wasi/src/lib.rs index 69c0f6b1cac..abc96368fc2 100644 --- a/lib/wasi/src/lib.rs +++ b/lib/wasi/src/lib.rs @@ -50,7 +50,6 @@ pub use crate::syscalls::types; pub use crate::utils::{ get_wasi_version, get_wasi_versions, is_wasi_module, is_wasix_module, WasiVersion, }; -use wasmer::ContextMut; pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus}; #[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")] pub use wasmer_vfs::FsError as WasiFsError; @@ -64,7 +63,7 @@ use derivative::*; use std::ops::Deref; use thiserror::Error; use wasmer::{ - imports, namespace, AsContextMut, Exports, Function, Imports, Memory, Memory32, + imports, namespace, AsStoreMut, Exports, Function, FunctionEnv, Imports, Memory, Memory32, MemoryAccessError, MemorySize, Module, TypedFunction, }; @@ -143,6 +142,65 @@ impl WasiThread { } } +pub struct WasiFunctionEnv { + pub env: FunctionEnv, +} + +impl WasiFunctionEnv { + pub fn new(store: &mut impl AsStoreMut, env: WasiEnv) -> Self { + Self { + env: FunctionEnv::new(store, env), + } + } + + /// Get an `Imports` for a specific version of WASI detected in the module. + pub fn import_object( + &self, + store: &mut impl AsStoreMut, + module: &Module, + ) -> Result { + let wasi_version = get_wasi_version(module, false).ok_or(WasiError::UnknownWasiVersion)?; + Ok(generate_import_object_from_env( + store, + &self.env, + wasi_version, + )) + } + + pub fn data_mut<'a>(&'a self, store: &'a mut impl AsStoreMut) -> &'a mut WasiEnv { + self.env.as_mut(store) + } + + /// Like `import_object` but containing all the WASI versions detected in + /// the module. + pub fn import_object_for_all_wasi_versions( + &self, + store: &mut impl AsStoreMut, + module: &Module, + ) -> Result { + let wasi_versions = + get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; + + let mut resolver = Imports::new(); + for version in wasi_versions.iter() { + let new_import_object = generate_import_object_from_env(store, &self.env, *version); + for ((n, m), e) in new_import_object.into_iter() { + resolver.define(&n, &m, e); + } + } + + if is_wasix_module(module) { + self.data_mut(store) + .state + .fs + .is_wasix + .store(true, std::sync::atomic::Ordering::Release); + } + + Ok(resolver) + } +} + /// The environment provided to the WASI imports. #[derive(Derivative, Clone)] #[derivative(Debug)] @@ -229,45 +287,6 @@ impl WasiEnv { self.memory.clone() } - /// Get an `Imports` for a specific version of WASI detected in the module. - pub fn import_object( - &mut self, - ctx: &mut ContextMut<'_, WasiEnv>, - module: &Module, - ) -> Result { - let wasi_version = get_wasi_version(module, false).ok_or(WasiError::UnknownWasiVersion)?; - Ok(generate_import_object_from_ctx(ctx, wasi_version)) - } - - /// Like `import_object` but containing all the WASI versions detected in - /// the module. - pub fn import_object_for_all_wasi_versions( - &mut self, - ctx: &mut ContextMut<'_, WasiEnv>, - module: &Module, - ) -> Result { - let wasi_versions = - get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?; - - let mut resolver = Imports::new(); - for version in wasi_versions.iter() { - let new_import_object = - generate_import_object_from_ctx(&mut ctx.as_context_mut(), *version); - for ((n, m), e) in new_import_object.into_iter() { - resolver.define(&n, &m, e); - } - } - - if is_wasix_module(module) { - self.state - .fs - .is_wasix - .store(true, std::sync::atomic::Ordering::Release); - } - - Ok(resolver) - } - // Yields execution pub fn yield_now(&self) -> Result<(), WasiError> { self.runtime.yield_now(self.id)?; @@ -357,122 +376,131 @@ impl WasiEnv { } /// Create an [`Imports`] from a [`Context`] -pub fn generate_import_object_from_ctx( - ctx: &mut ContextMut<'_, WasiEnv>, +pub fn generate_import_object_from_env( + store: &mut impl AsStoreMut, + ctx: &FunctionEnv, version: WasiVersion, ) -> Imports { match version { - WasiVersion::Snapshot0 => generate_import_object_snapshot0(ctx), - WasiVersion::Snapshot1 | WasiVersion::Latest => generate_import_object_snapshot1(ctx), - WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(ctx), - WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(ctx), + WasiVersion::Snapshot0 => generate_import_object_snapshot0(store, ctx), + WasiVersion::Snapshot1 | WasiVersion::Latest => { + generate_import_object_snapshot1(store, ctx) + } + WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, ctx), + WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, ctx), } } -fn wasi_unstable_exports(ctx: &mut ContextMut<'_, WasiEnv>) -> Exports { +fn wasi_unstable_exports(mut store: &mut impl AsStoreMut, ctx: &FunctionEnv) -> Exports { let namespace = namespace! { - "args_get" => Function::new_native(ctx, args_get::), - "args_sizes_get" => Function::new_native(ctx, args_sizes_get::), - "clock_res_get" => Function::new_native(ctx, clock_res_get::), - "clock_time_get" => Function::new_native(ctx, clock_time_get::), - "environ_get" => Function::new_native(ctx, environ_get::), - "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get::), - "fd_advise" => Function::new_native(ctx, fd_advise), - "fd_allocate" => Function::new_native(ctx, fd_allocate), - "fd_close" => Function::new_native(ctx, fd_close), - "fd_datasync" => Function::new_native(ctx, fd_datasync), - "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get::), - "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native(ctx, legacy::snapshot0::fd_filestat_get), - "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), - "fd_pread" => Function::new_native(ctx, fd_pread::), - "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get::), - "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name::), - "fd_pwrite" => Function::new_native(ctx, fd_pwrite::), - "fd_read" => Function::new_native(ctx, fd_read::), - "fd_readdir" => Function::new_native(ctx, fd_readdir::), - "fd_renumber" => Function::new_native(ctx, fd_renumber), - "fd_seek" => Function::new_native(ctx, legacy::snapshot0::fd_seek), - "fd_sync" => Function::new_native(ctx, fd_sync), - "fd_tell" => Function::new_native(ctx, fd_tell::), - "fd_write" => Function::new_native(ctx, fd_write::), - "path_create_directory" => Function::new_native(ctx, path_create_directory::), - "path_filestat_get" => Function::new_native(ctx, legacy::snapshot0::path_filestat_get), - "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times::), - "path_link" => Function::new_native(ctx, path_link::), - "path_open" => Function::new_native(ctx, path_open::), - "path_readlink" => Function::new_native(ctx, path_readlink::), - "path_remove_directory" => Function::new_native(ctx, path_remove_directory::), - "path_rename" => Function::new_native(ctx, path_rename::), - "path_symlink" => Function::new_native(ctx, path_symlink::), - "path_unlink_file" => Function::new_native(ctx, path_unlink_file::), - "poll_oneoff" => Function::new_native(ctx, legacy::snapshot0::poll_oneoff), - "proc_exit" => Function::new_native(ctx, proc_exit), - "proc_raise" => Function::new_native(ctx, proc_raise), - "random_get" => Function::new_native(ctx, random_get::), - "sched_yield" => Function::new_native(ctx, sched_yield), - "sock_recv" => Function::new_native(ctx, sock_recv::), - "sock_send" => Function::new_native(ctx, sock_send::), - "sock_shutdown" => Function::new_native(ctx, sock_shutdown), + "args_get" => Function::new_native(&mut store, ctx, args_get::), + "args_sizes_get" => Function::new_native(&mut store, ctx, args_sizes_get::), + "clock_res_get" => Function::new_native(&mut store, ctx, clock_res_get::), + "clock_time_get" => Function::new_native(&mut store, ctx, clock_time_get::), + "environ_get" => Function::new_native(&mut store, ctx, environ_get::), + "environ_sizes_get" => Function::new_native(&mut store, ctx, environ_sizes_get::), + "fd_advise" => Function::new_native(&mut store, ctx, fd_advise), + "fd_allocate" => Function::new_native(&mut store, ctx, fd_allocate), + "fd_close" => Function::new_native(&mut store, ctx, fd_close), + "fd_datasync" => Function::new_native(&mut store, ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(&mut store, ctx, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_native(&mut store, ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(&mut store, ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(&mut store, ctx, legacy::snapshot0::fd_filestat_get), + "fd_filestat_set_size" => Function::new_native(&mut store, ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(&mut store, ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(&mut store, ctx, fd_pread::), + "fd_prestat_get" => Function::new_native(&mut store, ctx, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_native(&mut store, ctx, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_native(&mut store, ctx, fd_pwrite::), + "fd_read" => Function::new_native(&mut store, ctx, fd_read::), + "fd_readdir" => Function::new_native(&mut store, ctx, fd_readdir::), + "fd_renumber" => Function::new_native(&mut store, ctx, fd_renumber), + "fd_seek" => Function::new_native(&mut store, ctx, legacy::snapshot0::fd_seek), + "fd_sync" => Function::new_native(&mut store, ctx, fd_sync), + "fd_tell" => Function::new_native(&mut store, ctx, fd_tell::), + "fd_write" => Function::new_native(&mut store, ctx, fd_write::), + "path_create_directory" => Function::new_native(&mut store, ctx, path_create_directory::), + "path_filestat_get" => Function::new_native(&mut store, ctx, legacy::snapshot0::path_filestat_get), + "path_filestat_set_times" => Function::new_native(&mut store, ctx, path_filestat_set_times::), + "path_link" => Function::new_native(&mut store, ctx, path_link::), + "path_open" => Function::new_native(&mut store, ctx, path_open::), + "path_readlink" => Function::new_native(&mut store, ctx, path_readlink::), + "path_remove_directory" => Function::new_native(&mut store, ctx, path_remove_directory::), + "path_rename" => Function::new_native(&mut store, ctx, path_rename::), + "path_symlink" => Function::new_native(&mut store, ctx, path_symlink::), + "path_unlink_file" => Function::new_native(&mut store, ctx, path_unlink_file::), + "poll_oneoff" => Function::new_native(&mut store, ctx, legacy::snapshot0::poll_oneoff), + "proc_exit" => Function::new_native(&mut store, ctx, proc_exit), + "proc_raise" => Function::new_native(&mut store, ctx, proc_raise), + "random_get" => Function::new_native(&mut store, ctx, random_get::), + "sched_yield" => Function::new_native(&mut store, ctx, sched_yield), + "sock_recv" => Function::new_native(&mut store, ctx, sock_recv::), + "sock_send" => Function::new_native(&mut store, ctx, sock_send::), + "sock_shutdown" => Function::new_native(&mut store, ctx, sock_shutdown), }; namespace } -fn wasi_snapshot_preview1_exports(ctx: &mut ContextMut<'_, WasiEnv>) -> Exports { +fn wasi_snapshot_preview1_exports( + mut store: &mut impl AsStoreMut, + ctx: &FunctionEnv, +) -> Exports { let namespace = namespace! { - "args_get" => Function::new_native(ctx, args_get::), - "args_sizes_get" => Function::new_native(ctx, args_sizes_get::), - "clock_res_get" => Function::new_native(ctx, clock_res_get::), - "clock_time_get" => Function::new_native(ctx, clock_time_get::), - "environ_get" => Function::new_native(ctx, environ_get::), - "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get::), - "fd_advise" => Function::new_native(ctx, fd_advise), - "fd_allocate" => Function::new_native(ctx, fd_allocate), - "fd_close" => Function::new_native(ctx, fd_close), - "fd_datasync" => Function::new_native(ctx, fd_datasync), - "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get::), - "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native(ctx, fd_filestat_get::), - "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), - "fd_pread" => Function::new_native(ctx, fd_pread::), - "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get::), - "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name::), - "fd_pwrite" => Function::new_native(ctx, fd_pwrite::), - "fd_read" => Function::new_native(ctx, fd_read::), - "fd_readdir" => Function::new_native(ctx, fd_readdir::), - "fd_renumber" => Function::new_native(ctx, fd_renumber), - "fd_seek" => Function::new_native(ctx, fd_seek::), - "fd_sync" => Function::new_native(ctx, fd_sync), - "fd_tell" => Function::new_native(ctx, fd_tell::), - "fd_write" => Function::new_native(ctx, fd_write::), - "path_create_directory" => Function::new_native(ctx, path_create_directory::), - "path_filestat_get" => Function::new_native(ctx, path_filestat_get::), - "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times::), - "path_link" => Function::new_native(ctx, path_link::), - "path_open" => Function::new_native(ctx, path_open::), - "path_readlink" => Function::new_native(ctx, path_readlink::), - "path_remove_directory" => Function::new_native(ctx, path_remove_directory::), - "path_rename" => Function::new_native(ctx, path_rename::), - "path_symlink" => Function::new_native(ctx, path_symlink::), - "path_unlink_file" => Function::new_native(ctx, path_unlink_file::), - "poll_oneoff" => Function::new_native(ctx, poll_oneoff::), - "proc_exit" => Function::new_native(ctx, proc_exit), - "proc_raise" => Function::new_native(ctx, proc_raise), - "random_get" => Function::new_native(ctx, random_get::), - "sched_yield" => Function::new_native(ctx, sched_yield), - "sock_recv" => Function::new_native(ctx, sock_recv::), - "sock_send" => Function::new_native(ctx, sock_send::), - "sock_shutdown" => Function::new_native(ctx, sock_shutdown), + "args_get" => Function::new_native(&mut store, ctx, args_get::), + "args_sizes_get" => Function::new_native(&mut store, ctx, args_sizes_get::), + "clock_res_get" => Function::new_native(&mut store, ctx, clock_res_get::), + "clock_time_get" => Function::new_native(&mut store, ctx, clock_time_get::), + "environ_get" => Function::new_native(&mut store, ctx, environ_get::), + "environ_sizes_get" => Function::new_native(&mut store, ctx, environ_sizes_get::), + "fd_advise" => Function::new_native(&mut store, ctx, fd_advise), + "fd_allocate" => Function::new_native(&mut store, ctx, fd_allocate), + "fd_close" => Function::new_native(&mut store, ctx, fd_close), + "fd_datasync" => Function::new_native(&mut store, ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(&mut store, ctx, fd_fdstat_get::), + "fd_fdstat_set_flags" => Function::new_native(&mut store, ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(&mut store, ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(&mut store, ctx, fd_filestat_get::), + "fd_filestat_set_size" => Function::new_native(&mut store, ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(&mut store, ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(&mut store, ctx, fd_pread::), + "fd_prestat_get" => Function::new_native(&mut store, ctx, fd_prestat_get::), + "fd_prestat_dir_name" => Function::new_native(&mut store, ctx, fd_prestat_dir_name::), + "fd_pwrite" => Function::new_native(&mut store, ctx, fd_pwrite::), + "fd_read" => Function::new_native(&mut store, ctx, fd_read::), + "fd_readdir" => Function::new_native(&mut store, ctx, fd_readdir::), + "fd_renumber" => Function::new_native(&mut store, ctx, fd_renumber), + "fd_seek" => Function::new_native(&mut store, ctx, fd_seek::), + "fd_sync" => Function::new_native(&mut store, ctx, fd_sync), + "fd_tell" => Function::new_native(&mut store, ctx, fd_tell::), + "fd_write" => Function::new_native(&mut store, ctx, fd_write::), + "path_create_directory" => Function::new_native(&mut store, ctx, path_create_directory::), + "path_filestat_get" => Function::new_native(&mut store, ctx, path_filestat_get::), + "path_filestat_set_times" => Function::new_native(&mut store, ctx, path_filestat_set_times::), + "path_link" => Function::new_native(&mut store, ctx, path_link::), + "path_open" => Function::new_native(&mut store, ctx, path_open::), + "path_readlink" => Function::new_native(&mut store, ctx, path_readlink::), + "path_remove_directory" => Function::new_native(&mut store, ctx, path_remove_directory::), + "path_rename" => Function::new_native(&mut store, ctx, path_rename::), + "path_symlink" => Function::new_native(&mut store, ctx, path_symlink::), + "path_unlink_file" => Function::new_native(&mut store, ctx, path_unlink_file::), + "poll_oneoff" => Function::new_native(&mut store, ctx, poll_oneoff::), + "proc_exit" => Function::new_native(&mut store, ctx, proc_exit), + "proc_raise" => Function::new_native(&mut store, ctx, proc_raise), + "random_get" => Function::new_native(&mut store, ctx, random_get::), + "sched_yield" => Function::new_native(&mut store, ctx, sched_yield), + "sock_recv" => Function::new_native(&mut store, ctx, sock_recv::), + "sock_send" => Function::new_native(&mut store, ctx, sock_send::), + "sock_shutdown" => Function::new_native(&mut store, ctx, sock_shutdown), }; namespace } -pub fn import_object_for_all_wasi_versions(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { - let wasi_unstable_exports = wasi_unstable_exports(ctx); - let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(ctx); +pub fn import_object_for_all_wasi_versions( + store: &mut impl AsStoreMut, + ctx: &FunctionEnv, +) -> Imports { + let wasi_unstable_exports = wasi_unstable_exports(store, ctx); + let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(store, ctx); imports! { "wasi_unstable" => wasi_unstable_exports, "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports, @@ -480,247 +508,259 @@ pub fn import_object_for_all_wasi_versions(ctx: &mut ContextMut<'_, WasiEnv>) -> } /// Combines a state generating function with the import list for legacy WASI -fn generate_import_object_snapshot0(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { - let wasi_unstable_exports = wasi_unstable_exports(ctx); +fn generate_import_object_snapshot0( + store: &mut impl AsStoreMut, + ctx: &FunctionEnv, +) -> Imports { + let wasi_unstable_exports = wasi_unstable_exports(store, ctx); imports! { "wasi_unstable" => wasi_unstable_exports } } -fn generate_import_object_snapshot1(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { - let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(ctx); +fn generate_import_object_snapshot1( + store: &mut impl AsStoreMut, + ctx: &FunctionEnv, +) -> Imports { + let wasi_snapshot_preview1_exports = wasi_snapshot_preview1_exports(store, ctx); imports! { "wasi_snapshot_preview1" => wasi_snapshot_preview1_exports } } /// Combines a state generating function with the import list for snapshot 1 -fn generate_import_object_wasix32_v1(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { +fn generate_import_object_wasix32_v1( + mut store: &mut impl AsStoreMut, + ctx: &FunctionEnv, +) -> Imports { use self::wasix32::*; imports! { "wasix_32v1" => { - "args_get" => Function::new_native(ctx, args_get), - "args_sizes_get" => Function::new_native(ctx, args_sizes_get), - "clock_res_get" => Function::new_native(ctx, clock_res_get), - "clock_time_get" => Function::new_native(ctx, clock_time_get), - "environ_get" => Function::new_native(ctx, environ_get), - "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get), - "fd_advise" => Function::new_native(ctx, fd_advise), - "fd_allocate" => Function::new_native(ctx, fd_allocate), - "fd_close" => Function::new_native(ctx, fd_close), - "fd_datasync" => Function::new_native(ctx, fd_datasync), - "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native(ctx, fd_filestat_get), - "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), - "fd_pread" => Function::new_native(ctx, fd_pread), - "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get), - "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name), - "fd_pwrite" => Function::new_native(ctx, fd_pwrite), - "fd_read" => Function::new_native(ctx, fd_read), - "fd_readdir" => Function::new_native(ctx, fd_readdir), - "fd_renumber" => Function::new_native(ctx, fd_renumber), - "fd_dup" => Function::new_native(ctx, fd_dup), - "fd_event" => Function::new_native(ctx, fd_event), - "fd_seek" => Function::new_native(ctx, fd_seek), - "fd_sync" => Function::new_native(ctx, fd_sync), - "fd_tell" => Function::new_native(ctx, fd_tell), - "fd_write" => Function::new_native(ctx, fd_write), - "fd_pipe" => Function::new_native(ctx, fd_pipe), - "path_create_directory" => Function::new_native(ctx, path_create_directory), - "path_filestat_get" => Function::new_native(ctx, path_filestat_get), - "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times), - "path_link" => Function::new_native(ctx, path_link), - "path_open" => Function::new_native(ctx, path_open), - "path_readlink" => Function::new_native(ctx, path_readlink), - "path_remove_directory" => Function::new_native(ctx, path_remove_directory), - "path_rename" => Function::new_native(ctx, path_rename), - "path_symlink" => Function::new_native(ctx, path_symlink), - "path_unlink_file" => Function::new_native(ctx, path_unlink_file), - "poll_oneoff" => Function::new_native(ctx, poll_oneoff), - "proc_exit" => Function::new_native(ctx, proc_exit), - "proc_raise" => Function::new_native(ctx, proc_raise), - "random_get" => Function::new_native(ctx, random_get), - "tty_get" => Function::new_native(ctx, tty_get), - "tty_set" => Function::new_native(ctx, tty_set), - "getcwd" => Function::new_native(ctx, getcwd), - "chdir" => Function::new_native(ctx, chdir), - "thread_spawn" => Function::new_native(ctx, thread_spawn), - "thread_sleep" => Function::new_native(ctx, thread_sleep), - "thread_id" => Function::new_native(ctx, thread_id), - "thread_join" => Function::new_native(ctx, thread_join), - "thread_parallelism" => Function::new_native(ctx, thread_parallelism), - "thread_exit" => Function::new_native(ctx, thread_exit), - "sched_yield" => Function::new_native(ctx, sched_yield), - "getpid" => Function::new_native(ctx, getpid), - "process_spawn" => Function::new_native(ctx, process_spawn), - "bus_open_local" => Function::new_native(ctx, bus_open_local), - "bus_open_remote" => Function::new_native(ctx, bus_open_remote), - "bus_close" => Function::new_native(ctx, bus_close), - "bus_call" => Function::new_native(ctx, bus_call), - "bus_subcall" => Function::new_native(ctx, bus_subcall), - "bus_poll" => Function::new_native(ctx, bus_poll), - "call_reply" => Function::new_native(ctx, call_reply), - "call_fault" => Function::new_native(ctx, call_fault), - "call_close" => Function::new_native(ctx, call_close), - "ws_connect" => Function::new_native(ctx, ws_connect), - "http_request" => Function::new_native(ctx, http_request), - "http_status" => Function::new_native(ctx, http_status), - "port_bridge" => Function::new_native(ctx, port_bridge), - "port_unbridge" => Function::new_native(ctx, port_unbridge), - "port_dhcp_acquire" => Function::new_native(ctx, port_dhcp_acquire), - "port_addr_add" => Function::new_native(ctx, port_addr_add), - "port_addr_remove" => Function::new_native(ctx, port_addr_remove), - "port_addr_clear" => Function::new_native(ctx, port_addr_clear), - "port_addr_list" => Function::new_native(ctx, port_addr_list), - "port_mac" => Function::new_native(ctx, port_mac), - "port_gateway_set" => Function::new_native(ctx, port_gateway_set), - "port_route_add" => Function::new_native(ctx, port_route_add), - "port_route_remove" => Function::new_native(ctx, port_route_remove), - "port_route_clear" => Function::new_native(ctx, port_route_clear), - "port_route_list" => Function::new_native(ctx, port_route_list), - "sock_status" => Function::new_native(ctx, sock_status), - "sock_addr_local" => Function::new_native(ctx, sock_addr_local), - "sock_addr_peer" => Function::new_native(ctx, sock_addr_peer), - "sock_open" => Function::new_native(ctx, sock_open), - "sock_set_opt_flag" => Function::new_native(ctx, sock_set_opt_flag), - "sock_get_opt_flag" => Function::new_native(ctx, sock_get_opt_flag), - "sock_set_opt_time" => Function::new_native(ctx, sock_set_opt_time), - "sock_get_opt_time" => Function::new_native(ctx, sock_get_opt_time), - "sock_set_opt_size" => Function::new_native(ctx, sock_set_opt_size), - "sock_get_opt_size" => Function::new_native(ctx, sock_get_opt_size), - "sock_join_multicast_v4" => Function::new_native(ctx, sock_join_multicast_v4), - "sock_leave_multicast_v4" => Function::new_native(ctx, sock_leave_multicast_v4), - "sock_join_multicast_v6" => Function::new_native(ctx, sock_join_multicast_v6), - "sock_leave_multicast_v6" => Function::new_native(ctx, sock_leave_multicast_v6), - "sock_bind" => Function::new_native(ctx, sock_bind), - "sock_listen" => Function::new_native(ctx, sock_listen), - "sock_accept" => Function::new_native(ctx, sock_accept), - "sock_connect" => Function::new_native(ctx, sock_connect), - "sock_recv" => Function::new_native(ctx, sock_recv), - "sock_recv_from" => Function::new_native(ctx, sock_recv_from), - "sock_send" => Function::new_native(ctx, sock_send), - "sock_send_to" => Function::new_native(ctx, sock_send_to), - "sock_send_file" => Function::new_native(ctx, sock_send_file), - "sock_shutdown" => Function::new_native(ctx, sock_shutdown), - "resolve" => Function::new_native(ctx, resolve), + "args_get" => Function::new_native(&mut store, ctx, args_get), + "args_sizes_get" => Function::new_native(&mut store, ctx, args_sizes_get), + "clock_res_get" => Function::new_native(&mut store, ctx, clock_res_get), + "clock_time_get" => Function::new_native(&mut store, ctx, clock_time_get), + "environ_get" => Function::new_native(&mut store, ctx, environ_get), + "environ_sizes_get" => Function::new_native(&mut store, ctx, environ_sizes_get), + "fd_advise" => Function::new_native(&mut store, ctx, fd_advise), + "fd_allocate" => Function::new_native(&mut store, ctx, fd_allocate), + "fd_close" => Function::new_native(&mut store, ctx, fd_close), + "fd_datasync" => Function::new_native(&mut store, ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(&mut store, ctx, fd_fdstat_get), + "fd_fdstat_set_flags" => Function::new_native(&mut store, ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(&mut store, ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(&mut store, ctx, fd_filestat_get), + "fd_filestat_set_size" => Function::new_native(&mut store, ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(&mut store, ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(&mut store, ctx, fd_pread), + "fd_prestat_get" => Function::new_native(&mut store, ctx, fd_prestat_get), + "fd_prestat_dir_name" => Function::new_native(&mut store, ctx, fd_prestat_dir_name), + "fd_pwrite" => Function::new_native(&mut store, ctx, fd_pwrite), + "fd_read" => Function::new_native(&mut store, ctx, fd_read), + "fd_readdir" => Function::new_native(&mut store, ctx, fd_readdir), + "fd_renumber" => Function::new_native(&mut store, ctx, fd_renumber), + "fd_dup" => Function::new_native(&mut store, ctx, fd_dup), + "fd_event" => Function::new_native(&mut store, ctx, fd_event), + "fd_seek" => Function::new_native(&mut store, ctx, fd_seek), + "fd_sync" => Function::new_native(&mut store, ctx, fd_sync), + "fd_tell" => Function::new_native(&mut store, ctx, fd_tell), + "fd_write" => Function::new_native(&mut store, ctx, fd_write), + "fd_pipe" => Function::new_native(&mut store, ctx, fd_pipe), + "path_create_directory" => Function::new_native(&mut store, ctx, path_create_directory), + "path_filestat_get" => Function::new_native(&mut store, ctx, path_filestat_get), + "path_filestat_set_times" => Function::new_native(&mut store, ctx, path_filestat_set_times), + "path_link" => Function::new_native(&mut store, ctx, path_link), + "path_open" => Function::new_native(&mut store, ctx, path_open), + "path_readlink" => Function::new_native(&mut store, ctx, path_readlink), + "path_remove_directory" => Function::new_native(&mut store, ctx, path_remove_directory), + "path_rename" => Function::new_native(&mut store, ctx, path_rename), + "path_symlink" => Function::new_native(&mut store, ctx, path_symlink), + "path_unlink_file" => Function::new_native(&mut store, ctx, path_unlink_file), + "poll_oneoff" => Function::new_native(&mut store, ctx, poll_oneoff), + "proc_exit" => Function::new_native(&mut store, ctx, proc_exit), + "proc_raise" => Function::new_native(&mut store, ctx, proc_raise), + "random_get" => Function::new_native(&mut store, ctx, random_get), + "tty_get" => Function::new_native(&mut store, ctx, tty_get), + "tty_set" => Function::new_native(&mut store, ctx, tty_set), + "getcwd" => Function::new_native(&mut store, ctx, getcwd), + "chdir" => Function::new_native(&mut store, ctx, chdir), + "thread_spawn" => Function::new_native(&mut store, ctx, thread_spawn), + "thread_sleep" => Function::new_native(&mut store, ctx, thread_sleep), + "thread_id" => Function::new_native(&mut store, ctx, thread_id), + "thread_join" => Function::new_native(&mut store, ctx, thread_join), + "thread_parallelism" => Function::new_native(&mut store, ctx, thread_parallelism), + "thread_exit" => Function::new_native(&mut store, ctx, thread_exit), + "sched_yield" => Function::new_native(&mut store, ctx, sched_yield), + "getpid" => Function::new_native(&mut store, ctx, getpid), + "process_spawn" => Function::new_native(&mut store, ctx, process_spawn), + "bus_open_local" => Function::new_native(&mut store, ctx, bus_open_local), + "bus_open_remote" => Function::new_native(&mut store, ctx, bus_open_remote), + "bus_close" => Function::new_native(&mut store, ctx, bus_close), + "bus_call" => Function::new_native(&mut store, ctx, bus_call), + "bus_subcall" => Function::new_native(&mut store, ctx, bus_subcall), + "bus_poll" => Function::new_native(&mut store, ctx, bus_poll), + "call_reply" => Function::new_native(&mut store, ctx, call_reply), + "call_fault" => Function::new_native(&mut store, ctx, call_fault), + "call_close" => Function::new_native(&mut store, ctx, call_close), + "ws_connect" => Function::new_native(&mut store, ctx, ws_connect), + "http_request" => Function::new_native(&mut store, ctx, http_request), + "http_status" => Function::new_native(&mut store, ctx, http_status), + "port_bridge" => Function::new_native(&mut store, ctx, port_bridge), + "port_unbridge" => Function::new_native(&mut store, ctx, port_unbridge), + "port_dhcp_acquire" => Function::new_native(&mut store, ctx, port_dhcp_acquire), + "port_addr_add" => Function::new_native(&mut store, ctx, port_addr_add), + "port_addr_remove" => Function::new_native(&mut store, ctx, port_addr_remove), + "port_addr_clear" => Function::new_native(&mut store, ctx, port_addr_clear), + "port_addr_list" => Function::new_native(&mut store, ctx, port_addr_list), + "port_mac" => Function::new_native(&mut store, ctx, port_mac), + "port_gateway_set" => Function::new_native(&mut store, ctx, port_gateway_set), + "port_route_add" => Function::new_native(&mut store, ctx, port_route_add), + "port_route_remove" => Function::new_native(&mut store, ctx, port_route_remove), + "port_route_clear" => Function::new_native(&mut store, ctx, port_route_clear), + "port_route_list" => Function::new_native(&mut store, ctx, port_route_list), + "sock_status" => Function::new_native(&mut store, ctx, sock_status), + "sock_addr_local" => Function::new_native(&mut store, ctx, sock_addr_local), + "sock_addr_peer" => Function::new_native(&mut store, ctx, sock_addr_peer), + "sock_open" => Function::new_native(&mut store, ctx, sock_open), + "sock_set_opt_flag" => Function::new_native(&mut store, ctx, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_native(&mut store, ctx, sock_get_opt_flag), + "sock_set_opt_time" => Function::new_native(&mut store, ctx, sock_set_opt_time), + "sock_get_opt_time" => Function::new_native(&mut store, ctx, sock_get_opt_time), + "sock_set_opt_size" => Function::new_native(&mut store, ctx, sock_set_opt_size), + "sock_get_opt_size" => Function::new_native(&mut store, ctx, sock_get_opt_size), + "sock_join_multicast_v4" => Function::new_native(&mut store, ctx, sock_join_multicast_v4), + "sock_leave_multicast_v4" => Function::new_native(&mut store, ctx, sock_leave_multicast_v4), + "sock_join_multicast_v6" => Function::new_native(&mut store, ctx, sock_join_multicast_v6), + "sock_leave_multicast_v6" => Function::new_native(&mut store, ctx, sock_leave_multicast_v6), + "sock_bind" => Function::new_native(&mut store, ctx, sock_bind), + "sock_listen" => Function::new_native(&mut store, ctx, sock_listen), + "sock_accept" => Function::new_native(&mut store, ctx, sock_accept), + "sock_connect" => Function::new_native(&mut store, ctx, sock_connect), + "sock_recv" => Function::new_native(&mut store, ctx, sock_recv), + "sock_recv_from" => Function::new_native(&mut store, ctx, sock_recv_from), + "sock_send" => Function::new_native(&mut store, ctx, sock_send), + "sock_send_to" => Function::new_native(&mut store, ctx, sock_send_to), + "sock_send_file" => Function::new_native(&mut store, ctx, sock_send_file), + "sock_shutdown" => Function::new_native(&mut store, ctx, sock_shutdown), + "resolve" => Function::new_native(&mut store, ctx, resolve), } } } -fn generate_import_object_wasix64_v1(ctx: &mut ContextMut<'_, WasiEnv>) -> Imports { +fn generate_import_object_wasix64_v1( + mut store: &mut impl AsStoreMut, + ctx: &FunctionEnv, +) -> Imports { use self::wasix64::*; imports! { "wasix_64v1" => { - "args_get" => Function::new_native(ctx, args_get), - "args_sizes_get" => Function::new_native(ctx, args_sizes_get), - "clock_res_get" => Function::new_native(ctx, clock_res_get), - "clock_time_get" => Function::new_native(ctx, clock_time_get), - "environ_get" => Function::new_native(ctx, environ_get), - "environ_sizes_get" => Function::new_native(ctx, environ_sizes_get), - "fd_advise" => Function::new_native(ctx, fd_advise), - "fd_allocate" => Function::new_native(ctx, fd_allocate), - "fd_close" => Function::new_native(ctx, fd_close), - "fd_datasync" => Function::new_native(ctx, fd_datasync), - "fd_fdstat_get" => Function::new_native(ctx, fd_fdstat_get), - "fd_fdstat_set_flags" => Function::new_native(ctx, fd_fdstat_set_flags), - "fd_fdstat_set_rights" => Function::new_native(ctx, fd_fdstat_set_rights), - "fd_filestat_get" => Function::new_native(ctx, fd_filestat_get), - "fd_filestat_set_size" => Function::new_native(ctx, fd_filestat_set_size), - "fd_filestat_set_times" => Function::new_native(ctx, fd_filestat_set_times), - "fd_pread" => Function::new_native(ctx, fd_pread), - "fd_prestat_get" => Function::new_native(ctx, fd_prestat_get), - "fd_prestat_dir_name" => Function::new_native(ctx, fd_prestat_dir_name), - "fd_pwrite" => Function::new_native(ctx, fd_pwrite), - "fd_read" => Function::new_native(ctx, fd_read), - "fd_readdir" => Function::new_native(ctx, fd_readdir), - "fd_renumber" => Function::new_native(ctx, fd_renumber), - "fd_dup" => Function::new_native(ctx, fd_dup), - "fd_event" => Function::new_native(ctx, fd_event), - "fd_seek" => Function::new_native(ctx, fd_seek), - "fd_sync" => Function::new_native(ctx, fd_sync), - "fd_tell" => Function::new_native(ctx, fd_tell), - "fd_write" => Function::new_native(ctx, fd_write), - "fd_pipe" => Function::new_native(ctx, fd_pipe), - "path_create_directory" => Function::new_native(ctx, path_create_directory), - "path_filestat_get" => Function::new_native(ctx, path_filestat_get), - "path_filestat_set_times" => Function::new_native(ctx, path_filestat_set_times), - "path_link" => Function::new_native(ctx, path_link), - "path_open" => Function::new_native(ctx, path_open), - "path_readlink" => Function::new_native(ctx, path_readlink), - "path_remove_directory" => Function::new_native(ctx, path_remove_directory), - "path_rename" => Function::new_native(ctx, path_rename), - "path_symlink" => Function::new_native(ctx, path_symlink), - "path_unlink_file" => Function::new_native(ctx, path_unlink_file), - "poll_oneoff" => Function::new_native(ctx, poll_oneoff), - "proc_exit" => Function::new_native(ctx, proc_exit), - "proc_raise" => Function::new_native(ctx, proc_raise), - "random_get" => Function::new_native(ctx, random_get), - "tty_get" => Function::new_native(ctx, tty_get), - "tty_set" => Function::new_native(ctx, tty_set), - "getcwd" => Function::new_native(ctx, getcwd), - "chdir" => Function::new_native(ctx, chdir), - "thread_spawn" => Function::new_native(ctx, thread_spawn), - "thread_sleep" => Function::new_native(ctx, thread_sleep), - "thread_id" => Function::new_native(ctx, thread_id), - "thread_join" => Function::new_native(ctx, thread_join), - "thread_parallelism" => Function::new_native(ctx, thread_parallelism), - "thread_exit" => Function::new_native(ctx, thread_exit), - "sched_yield" => Function::new_native(ctx, sched_yield), - "getpid" => Function::new_native(ctx, getpid), - "process_spawn" => Function::new_native(ctx, process_spawn), - "bus_open_local" => Function::new_native(ctx, bus_open_local), - "bus_open_remote" => Function::new_native(ctx, bus_open_remote), - "bus_close" => Function::new_native(ctx, bus_close), - "bus_call" => Function::new_native(ctx, bus_call), - "bus_subcall" => Function::new_native(ctx, bus_subcall), - "bus_poll" => Function::new_native(ctx, bus_poll), - "call_reply" => Function::new_native(ctx, call_reply), - "call_fault" => Function::new_native(ctx, call_fault), - "call_close" => Function::new_native(ctx, call_close), - "ws_connect" => Function::new_native(ctx, ws_connect), - "http_request" => Function::new_native(ctx, http_request), - "http_status" => Function::new_native(ctx, http_status), - "port_bridge" => Function::new_native(ctx, port_bridge), - "port_unbridge" => Function::new_native(ctx, port_unbridge), - "port_dhcp_acquire" => Function::new_native(ctx, port_dhcp_acquire), - "port_addr_add" => Function::new_native(ctx, port_addr_add), - "port_addr_remove" => Function::new_native(ctx, port_addr_remove), - "port_addr_clear" => Function::new_native(ctx, port_addr_clear), - "port_addr_list" => Function::new_native(ctx, port_addr_list), - "port_mac" => Function::new_native(ctx, port_mac), - "port_gateway_set" => Function::new_native(ctx, port_gateway_set), - "port_route_add" => Function::new_native(ctx, port_route_add), - "port_route_remove" => Function::new_native(ctx, port_route_remove), - "port_route_clear" => Function::new_native(ctx, port_route_clear), - "port_route_list" => Function::new_native(ctx, port_route_list), - "sock_status" => Function::new_native(ctx, sock_status), - "sock_addr_local" => Function::new_native(ctx, sock_addr_local), - "sock_addr_peer" => Function::new_native(ctx, sock_addr_peer), - "sock_open" => Function::new_native(ctx, sock_open), - "sock_set_opt_flag" => Function::new_native(ctx, sock_set_opt_flag), - "sock_get_opt_flag" => Function::new_native(ctx, sock_get_opt_flag), - "sock_set_opt_time" => Function::new_native(ctx, sock_set_opt_time), - "sock_get_opt_time" => Function::new_native(ctx, sock_get_opt_time), - "sock_set_opt_size" => Function::new_native(ctx, sock_set_opt_size), - "sock_get_opt_size" => Function::new_native(ctx, sock_get_opt_size), - "sock_join_multicast_v4" => Function::new_native(ctx, sock_join_multicast_v4), - "sock_leave_multicast_v4" => Function::new_native(ctx, sock_leave_multicast_v4), - "sock_join_multicast_v6" => Function::new_native(ctx, sock_join_multicast_v6), - "sock_leave_multicast_v6" => Function::new_native(ctx, sock_leave_multicast_v6), - "sock_bind" => Function::new_native(ctx, sock_bind), - "sock_listen" => Function::new_native(ctx, sock_listen), - "sock_accept" => Function::new_native(ctx, sock_accept), - "sock_connect" => Function::new_native(ctx, sock_connect), - "sock_recv" => Function::new_native(ctx, sock_recv), - "sock_recv_from" => Function::new_native(ctx, sock_recv_from), - "sock_send" => Function::new_native(ctx, sock_send), - "sock_send_to" => Function::new_native(ctx, sock_send_to), - "sock_send_file" => Function::new_native(ctx, sock_send_file), - "sock_shutdown" => Function::new_native(ctx, sock_shutdown), - "resolve" => Function::new_native(ctx, resolve), + "args_get" => Function::new_native(&mut store, ctx, args_get), + "args_sizes_get" => Function::new_native(&mut store, ctx, args_sizes_get), + "clock_res_get" => Function::new_native(&mut store, ctx, clock_res_get), + "clock_time_get" => Function::new_native(&mut store, ctx, clock_time_get), + "environ_get" => Function::new_native(&mut store, ctx, environ_get), + "environ_sizes_get" => Function::new_native(&mut store, ctx, environ_sizes_get), + "fd_advise" => Function::new_native(&mut store, ctx, fd_advise), + "fd_allocate" => Function::new_native(&mut store, ctx, fd_allocate), + "fd_close" => Function::new_native(&mut store, ctx, fd_close), + "fd_datasync" => Function::new_native(&mut store, ctx, fd_datasync), + "fd_fdstat_get" => Function::new_native(&mut store, ctx, fd_fdstat_get), + "fd_fdstat_set_flags" => Function::new_native(&mut store, ctx, fd_fdstat_set_flags), + "fd_fdstat_set_rights" => Function::new_native(&mut store, ctx, fd_fdstat_set_rights), + "fd_filestat_get" => Function::new_native(&mut store, ctx, fd_filestat_get), + "fd_filestat_set_size" => Function::new_native(&mut store, ctx, fd_filestat_set_size), + "fd_filestat_set_times" => Function::new_native(&mut store, ctx, fd_filestat_set_times), + "fd_pread" => Function::new_native(&mut store, ctx, fd_pread), + "fd_prestat_get" => Function::new_native(&mut store, ctx, fd_prestat_get), + "fd_prestat_dir_name" => Function::new_native(&mut store, ctx, fd_prestat_dir_name), + "fd_pwrite" => Function::new_native(&mut store, ctx, fd_pwrite), + "fd_read" => Function::new_native(&mut store, ctx, fd_read), + "fd_readdir" => Function::new_native(&mut store, ctx, fd_readdir), + "fd_renumber" => Function::new_native(&mut store, ctx, fd_renumber), + "fd_dup" => Function::new_native(&mut store, ctx, fd_dup), + "fd_event" => Function::new_native(&mut store, ctx, fd_event), + "fd_seek" => Function::new_native(&mut store, ctx, fd_seek), + "fd_sync" => Function::new_native(&mut store, ctx, fd_sync), + "fd_tell" => Function::new_native(&mut store, ctx, fd_tell), + "fd_write" => Function::new_native(&mut store, ctx, fd_write), + "fd_pipe" => Function::new_native(&mut store, ctx, fd_pipe), + "path_create_directory" => Function::new_native(&mut store, ctx, path_create_directory), + "path_filestat_get" => Function::new_native(&mut store, ctx, path_filestat_get), + "path_filestat_set_times" => Function::new_native(&mut store, ctx, path_filestat_set_times), + "path_link" => Function::new_native(&mut store, ctx, path_link), + "path_open" => Function::new_native(&mut store, ctx, path_open), + "path_readlink" => Function::new_native(&mut store, ctx, path_readlink), + "path_remove_directory" => Function::new_native(&mut store, ctx, path_remove_directory), + "path_rename" => Function::new_native(&mut store, ctx, path_rename), + "path_symlink" => Function::new_native(&mut store, ctx, path_symlink), + "path_unlink_file" => Function::new_native(&mut store, ctx, path_unlink_file), + "poll_oneoff" => Function::new_native(&mut store, ctx, poll_oneoff), + "proc_exit" => Function::new_native(&mut store, ctx, proc_exit), + "proc_raise" => Function::new_native(&mut store, ctx, proc_raise), + "random_get" => Function::new_native(&mut store, ctx, random_get), + "tty_get" => Function::new_native(&mut store, ctx, tty_get), + "tty_set" => Function::new_native(&mut store, ctx, tty_set), + "getcwd" => Function::new_native(&mut store, ctx, getcwd), + "chdir" => Function::new_native(&mut store, ctx, chdir), + "thread_spawn" => Function::new_native(&mut store, ctx, thread_spawn), + "thread_sleep" => Function::new_native(&mut store, ctx, thread_sleep), + "thread_id" => Function::new_native(&mut store, ctx, thread_id), + "thread_join" => Function::new_native(&mut store, ctx, thread_join), + "thread_parallelism" => Function::new_native(&mut store, ctx, thread_parallelism), + "thread_exit" => Function::new_native(&mut store, ctx, thread_exit), + "sched_yield" => Function::new_native(&mut store, ctx, sched_yield), + "getpid" => Function::new_native(&mut store, ctx, getpid), + "process_spawn" => Function::new_native(&mut store, ctx, process_spawn), + "bus_open_local" => Function::new_native(&mut store, ctx, bus_open_local), + "bus_open_remote" => Function::new_native(&mut store, ctx, bus_open_remote), + "bus_close" => Function::new_native(&mut store, ctx, bus_close), + "bus_call" => Function::new_native(&mut store, ctx, bus_call), + "bus_subcall" => Function::new_native(&mut store, ctx, bus_subcall), + "bus_poll" => Function::new_native(&mut store, ctx, bus_poll), + "call_reply" => Function::new_native(&mut store, ctx, call_reply), + "call_fault" => Function::new_native(&mut store, ctx, call_fault), + "call_close" => Function::new_native(&mut store, ctx, call_close), + "ws_connect" => Function::new_native(&mut store, ctx, ws_connect), + "http_request" => Function::new_native(&mut store, ctx, http_request), + "http_status" => Function::new_native(&mut store, ctx, http_status), + "port_bridge" => Function::new_native(&mut store, ctx, port_bridge), + "port_unbridge" => Function::new_native(&mut store, ctx, port_unbridge), + "port_dhcp_acquire" => Function::new_native(&mut store, ctx, port_dhcp_acquire), + "port_addr_add" => Function::new_native(&mut store, ctx, port_addr_add), + "port_addr_remove" => Function::new_native(&mut store, ctx, port_addr_remove), + "port_addr_clear" => Function::new_native(&mut store, ctx, port_addr_clear), + "port_addr_list" => Function::new_native(&mut store, ctx, port_addr_list), + "port_mac" => Function::new_native(&mut store, ctx, port_mac), + "port_gateway_set" => Function::new_native(&mut store, ctx, port_gateway_set), + "port_route_add" => Function::new_native(&mut store, ctx, port_route_add), + "port_route_remove" => Function::new_native(&mut store, ctx, port_route_remove), + "port_route_clear" => Function::new_native(&mut store, ctx, port_route_clear), + "port_route_list" => Function::new_native(&mut store, ctx, port_route_list), + "sock_status" => Function::new_native(&mut store, ctx, sock_status), + "sock_addr_local" => Function::new_native(&mut store, ctx, sock_addr_local), + "sock_addr_peer" => Function::new_native(&mut store, ctx, sock_addr_peer), + "sock_open" => Function::new_native(&mut store, ctx, sock_open), + "sock_set_opt_flag" => Function::new_native(&mut store, ctx, sock_set_opt_flag), + "sock_get_opt_flag" => Function::new_native(&mut store, ctx, sock_get_opt_flag), + "sock_set_opt_time" => Function::new_native(&mut store, ctx, sock_set_opt_time), + "sock_get_opt_time" => Function::new_native(&mut store, ctx, sock_get_opt_time), + "sock_set_opt_size" => Function::new_native(&mut store, ctx, sock_set_opt_size), + "sock_get_opt_size" => Function::new_native(&mut store, ctx, sock_get_opt_size), + "sock_join_multicast_v4" => Function::new_native(&mut store, ctx, sock_join_multicast_v4), + "sock_leave_multicast_v4" => Function::new_native(&mut store, ctx, sock_leave_multicast_v4), + "sock_join_multicast_v6" => Function::new_native(&mut store, ctx, sock_join_multicast_v6), + "sock_leave_multicast_v6" => Function::new_native(&mut store, ctx, sock_leave_multicast_v6), + "sock_bind" => Function::new_native(&mut store, ctx, sock_bind), + "sock_listen" => Function::new_native(&mut store, ctx, sock_listen), + "sock_accept" => Function::new_native(&mut store, ctx, sock_accept), + "sock_connect" => Function::new_native(&mut store, ctx, sock_connect), + "sock_recv" => Function::new_native(&mut store, ctx, sock_recv), + "sock_recv_from" => Function::new_native(&mut store, ctx, sock_recv_from), + "sock_send" => Function::new_native(&mut store, ctx, sock_send), + "sock_send_to" => Function::new_native(&mut store, ctx, sock_send_to), + "sock_send_file" => Function::new_native(&mut store, ctx, sock_send_file), + "sock_shutdown" => Function::new_native(&mut store, ctx, sock_shutdown), + "resolve" => Function::new_native(&mut store, ctx, resolve), } } } diff --git a/lib/wasi/src/state/builder.rs b/lib/wasi/src/state/builder.rs index 541b0a4a923..3cacd30a24e 100644 --- a/lib/wasi/src/state/builder.rs +++ b/lib/wasi/src/state/builder.rs @@ -2,7 +2,7 @@ use crate::state::{default_fs_backing, WasiFs, WasiState}; use crate::syscalls::types::{__WASI_STDERR_FILENO, __WASI_STDIN_FILENO, __WASI_STDOUT_FILENO}; -use crate::{WasiEnv, WasiInodes}; +use crate::{WasiEnv, WasiFunctionEnv, WasiInodes}; use generational_arena::Arena; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; @@ -10,6 +10,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::sync::RwLock; use thiserror::Error; +use wasmer::AsStoreMut; use wasmer_vfs::{FsError, VirtualFile}; /// Creates an empty [`WasiStateBuilder`]. @@ -493,14 +494,17 @@ impl WasiStateBuilder { /// determinisic result. This method is calling [Self::build], /// which is changing the builder's internal state. See /// [Self::build]'s documentation to learn more. - pub fn finalize(&mut self) -> Result { + pub fn finalize( + &mut self, + store: &mut impl AsStoreMut, + ) -> Result { let state = self.build()?; let mut env = WasiEnv::new(state); if let Some(runtime) = self.runtime_override.as_ref() { env.runtime = runtime.clone(); } - Ok(env) + Ok(WasiFunctionEnv::new(store, env)) } } diff --git a/lib/wasi/src/state/pipe.rs b/lib/wasi/src/state/pipe.rs index 29ccb9373ba..2f419214537 100644 --- a/lib/wasi/src/state/pipe.rs +++ b/lib/wasi/src/state/pipe.rs @@ -8,7 +8,7 @@ use std::ops::DerefMut; use std::sync::mpsc; use std::sync::Mutex; use wasmer::MemorySize; -use wasmer::{ContextMut, Memory, WasmSlice}; +use wasmer::{FunctionEnvMut, Memory, WasmSlice}; #[derive(Debug)] pub struct WasiPipe { @@ -42,7 +42,7 @@ impl WasiPipe { pub fn recv( &mut self, - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_iovec_t>, ) -> Result { @@ -64,7 +64,7 @@ impl WasiPipe { pub fn send( &mut self, - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, memory: &Memory, iov: WasmSlice<__wasi_ciovec_t>, ) -> Result { diff --git a/lib/wasi/src/state/socket.rs b/lib/wasi/src/state/socket.rs index d2ab0e7ae6a..ff4e92eca45 100644 --- a/lib/wasi/src/state/socket.rs +++ b/lib/wasi/src/state/socket.rs @@ -11,7 +11,7 @@ use std::sync::Mutex; use std::time::Duration; #[allow(unused_imports)] use tracing::{debug, error, info, warn}; -use wasmer::{ContextMut, Memory, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{FunctionEnvMut, Memory, MemorySize, WasmPtr, WasmSlice}; use wasmer_vnet::{net_error_into_io_err, TimeType}; use wasmer_vnet::{ IpCidr, IpRoute, SocketHttpRequest, VirtualIcmpSocket, VirtualNetworking, VirtualRawSocket, @@ -769,7 +769,7 @@ impl InodeSocket { pub fn send( &mut self, - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, iov: WasmSlice<__wasi_ciovec_t>, ) -> Result { @@ -854,7 +854,7 @@ impl InodeSocket { pub fn send_to( &mut self, - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, iov: WasmSlice<__wasi_ciovec_t>, addr: WasmPtr<__wasi_addr_port_t, M>, @@ -885,7 +885,7 @@ impl InodeSocket { pub fn recv( &mut self, - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, iov: WasmSlice<__wasi_iovec_t>, ) -> Result { @@ -955,7 +955,7 @@ impl InodeSocket { pub fn recv_from( &mut self, - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, iov: WasmSlice<__wasi_iovec_t>, addr: WasmPtr<__wasi_addr_port_t, M>, @@ -1135,7 +1135,7 @@ impl Drop for InodeSocket { #[allow(dead_code)] pub(crate) fn read_ip( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_addr_t, M>, ) -> Result { @@ -1154,7 +1154,7 @@ pub(crate) fn read_ip( } pub(crate) fn read_ip_v4( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_addr_ip4_t, M>, ) -> Result { @@ -1166,7 +1166,7 @@ pub(crate) fn read_ip_v4( } pub(crate) fn read_ip_v6( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_addr_ip6_t, M>, ) -> Result { @@ -1178,7 +1178,7 @@ pub(crate) fn read_ip_v6( } pub(crate) fn write_ip( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_addr_t, M>, ip: IpAddr, @@ -1209,7 +1209,7 @@ pub(crate) fn write_ip( #[allow(dead_code)] pub(crate) fn read_cidr( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_cidr_t, M>, ) -> Result { @@ -1241,7 +1241,7 @@ pub(crate) fn read_cidr( #[allow(dead_code)] pub(crate) fn write_cidr( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_cidr_t, M>, cidr: IpCidr, @@ -1279,7 +1279,7 @@ pub(crate) fn write_cidr( } pub(crate) fn read_ip_port( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_addr_port_t, M>, ) -> Result<(IpAddr, u16), __wasi_errno_t> { @@ -1311,7 +1311,7 @@ pub(crate) fn read_ip_port( #[allow(dead_code)] pub(crate) fn write_ip_port( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_addr_port_t, M>, ip: IpAddr, @@ -1351,7 +1351,7 @@ pub(crate) fn write_ip_port( #[allow(dead_code)] pub(crate) fn read_route( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_route_t, M>, ) -> Result { @@ -1407,7 +1407,7 @@ pub(crate) fn read_route( } pub(crate) fn write_route( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut, memory: &Memory, ptr: WasmPtr<__wasi_route_t, M>, route: IpRoute, diff --git a/lib/wasi/src/syscalls/legacy/snapshot0.rs b/lib/wasi/src/syscalls/legacy/snapshot0.rs index 96a1eed7090..33c2f1f6427 100644 --- a/lib/wasi/src/syscalls/legacy/snapshot0.rs +++ b/lib/wasi/src/syscalls/legacy/snapshot0.rs @@ -1,7 +1,7 @@ use crate::syscalls; use crate::syscalls::types::{self, snapshot0}; use crate::{mem_error_to_wasi, Memory32, MemorySize, WasiEnv, WasiError, WasiThread}; -use wasmer::{AsContextMut, ContextMut, WasmPtr}; +use wasmer::{AsStoreMut, FunctionEnvMut, WasmPtr}; /// Wrapper around `syscalls::fd_filestat_get` with extra logic to handle the size /// difference of `wasi_filestat_t` @@ -10,7 +10,7 @@ use wasmer::{AsContextMut, ContextMut, WasmPtr}; /// Wasm memory. If the memory clobbered by the current syscall is also used by /// that syscall, then it may break. pub fn fd_filestat_get( - mut ctx: ContextMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut, fd: types::__wasi_fd_t, buf: WasmPtr, ) -> types::__wasi_errno_t { @@ -27,7 +27,7 @@ pub fn fd_filestat_get( // Set up complete, make the call with the pointer that will write to the // struct and some unrelated memory after the struct. - let result = syscalls::fd_filestat_get::(ctx.as_context_mut(), fd, new_buf); + let result = syscalls::fd_filestat_get::(ctx.as_mut(), fd, new_buf); // reborrow memory let env = ctx.data(); @@ -61,7 +61,7 @@ pub fn fd_filestat_get( /// Wrapper around `syscalls::path_filestat_get` with extra logic to handle the size /// difference of `wasi_filestat_t` pub fn path_filestat_get( - mut ctx: ContextMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut, fd: types::__wasi_fd_t, flags: types::__wasi_lookupflags_t, path: WasmPtr, @@ -75,14 +75,8 @@ pub fn path_filestat_get( let new_buf: WasmPtr = buf.cast(); let new_filestat_setup: types::__wasi_filestat_t = wasi_try_mem!(new_buf.read(&ctx, memory)); - let result = syscalls::path_filestat_get::( - ctx.as_context_mut(), - fd, - flags, - path, - path_len, - new_buf, - ); + let result = + syscalls::path_filestat_get::(ctx.as_mut(), fd, flags, path, path_len, new_buf); // need to re-borrow let env = ctx.data(); @@ -108,7 +102,7 @@ pub fn path_filestat_get( /// Wrapper around `syscalls::fd_seek` with extra logic to remap the values /// of `__wasi_whence_t` pub fn fd_seek( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: types::__wasi_fd_t, offset: types::__wasi_filedelta_t, whence: snapshot0::__wasi_whence_t, @@ -127,7 +121,7 @@ pub fn fd_seek( /// Wrapper around `syscalls::poll_oneoff` with extra logic to add the removed /// userdata field back pub fn poll_oneoff( - mut ctx: ContextMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut, in_: WasmPtr, out_: WasmPtr, nsubscriptions: u32, @@ -173,7 +167,7 @@ pub fn poll_oneoff( // make the call let result = syscalls::poll_oneoff::( - ctx.as_context_mut(), + ctx.as_mut(), in_new_type_ptr, out_, nsubscriptions, diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index 1c2e04f3b11..32e1a09492a 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -47,8 +47,8 @@ use std::sync::{mpsc, Arc}; use std::time::Duration; use tracing::{debug, error, trace, warn}; use wasmer::{ - AsContextMut, ContextMut, Memory, Memory32, Memory64, MemorySize, RuntimeError, Value, WasmPtr, - WasmSlice, + AsStoreMut, FunctionEnvMut, Memory, Memory32, Memory64, MemorySize, RuntimeError, Value, + WasmPtr, WasmSlice, }; use wasmer_vbus::{FileDescriptor, StdioMode}; use wasmer_vfs::{FsError, VirtualFile}; @@ -79,7 +79,7 @@ fn from_offset(offset: M::Offset) -> Result( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, mut write_loc: T, memory: &Memory, iovs_arr_cell: WasmSlice<__wasi_ciovec_t>, @@ -99,7 +99,7 @@ fn write_bytes_inner( } pub(crate) fn write_bytes( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, mut write_loc: T, memory: &Memory, iovs_arr: WasmSlice<__wasi_ciovec_t>, @@ -110,7 +110,7 @@ pub(crate) fn write_bytes( } pub(crate) fn read_bytes( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, mut reader: T, memory: &Memory, iovs_arr: WasmSlice<__wasi_iovec_t>, @@ -141,7 +141,7 @@ fn has_rights(rights_set: __wasi_rights_t, rights_check_set: __wasi_rights_t) -> } fn __sock_actor( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, rights: __wasi_rights_t, actor: F, @@ -174,7 +174,7 @@ where } fn __sock_actor_mut( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, rights: __wasi_rights_t, actor: F, @@ -207,7 +207,7 @@ where } fn __sock_upgrade( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, rights: __wasi_rights_t, actor: F, @@ -247,7 +247,7 @@ where #[must_use] fn write_buffer_array( - ctx: &ContextMut<'_, WasiEnv>, + ctx: &FunctionEnvMut<'_, WasiEnv>, memory: &Memory, from: &[Vec], ptr_buffer: WasmPtr, M>, @@ -297,7 +297,7 @@ fn get_current_time_in_nanos() -> Result<__wasi_timestamp_t, __wasi_errno_t> { /// A pointer to a buffer to write the argument string data. /// pub fn args_get( - mut ctx: ContextMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut<'_, WasiEnv>, argv: WasmPtr, M>, argv_buf: WasmPtr, ) -> __wasi_errno_t { @@ -329,7 +329,7 @@ pub fn args_get( /// - `size_t *argv_buf_size` /// The size of the argument string data. pub fn args_sizes_get( - mut ctx: ContextMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut<'_, WasiEnv>, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -361,7 +361,7 @@ pub fn args_sizes_get( /// - `__wasi_timestamp_t *resolution` /// The resolution of the clock in nanoseconds pub fn clock_res_get( - mut ctx: ContextMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, M>, ) -> __wasi_errno_t { @@ -386,7 +386,7 @@ pub fn clock_res_get( /// - `__wasi_timestamp_t *time` /// The value of the clock in nanoseconds pub fn clock_time_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, M>, @@ -419,7 +419,7 @@ pub fn clock_time_get( /// - `char *environ_buf` /// A pointer to a buffer to write the environment variable string data. pub fn environ_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, environ: WasmPtr, M>, environ_buf: WasmPtr, ) -> __wasi_errno_t { @@ -442,7 +442,7 @@ pub fn environ_get( /// - `size_t *environ_buf_size` /// The size of the environment variable string data. pub fn environ_sizes_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -481,7 +481,7 @@ pub fn environ_sizes_get( /// - `__wasi_advice_t advice` /// The advice to give pub fn fd_advise( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -504,7 +504,7 @@ pub fn fd_advise( /// - `__wasi_filesize_t len` /// The length from the offset marking the end of the allocation pub fn fd_allocate( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -555,7 +555,7 @@ pub fn fd_allocate( /// If `fd` is a directory /// - `__WASI_EBADF` /// If `fd` is invalid or not open -pub fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_close(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_close: fd={}", fd); let env = ctx.data(); let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); @@ -572,7 +572,7 @@ pub fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t /// Inputs: /// - `__wasi_fd_t fd` /// The file descriptor to sync -pub fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_datasync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_datasync"); let env = ctx.data(); let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(0); @@ -597,7 +597,7 @@ pub fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errn /// - `__wasi_fdstat_t *buf` /// The location where the metadata will be written pub fn fd_fdstat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, M>, ) -> __wasi_errno_t { @@ -625,7 +625,7 @@ pub fn fd_fdstat_get( /// - `__wasi_fdflags_t flags` /// The flags to apply to `fd` pub fn fd_fdstat_set_flags( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { @@ -653,7 +653,7 @@ pub fn fd_fdstat_set_flags( /// - `__wasi_rights_t fs_rights_inheriting` /// The inheriting rights to apply to `fd` pub fn fd_fdstat_set_rights( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, @@ -686,7 +686,7 @@ pub fn fd_fdstat_set_rights( /// - `__wasi_filestat_t *buf` /// Where the metadata from `fd` will be written pub fn fd_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, M>, ) -> __wasi_errno_t { @@ -714,7 +714,7 @@ pub fn fd_filestat_get( /// - `__wasi_filesize_t st_size` /// New size that `fd` will be set to pub fn fd_filestat_set_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { @@ -763,7 +763,7 @@ pub fn fd_filestat_set_size( /// - `__wasi_fstflags_t fst_flags` /// Bit-vector for controlling which times get set pub fn fd_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, @@ -825,7 +825,7 @@ pub fn fd_filestat_set_times( /// - `size_t nread` /// The number of bytes read pub fn fd_pread( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, M>, iovs_len: M::Offset, @@ -916,7 +916,7 @@ pub fn fd_pread( /// - `__wasi_prestat *buf` /// Where the metadata will be written pub fn fd_prestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, M>, ) -> __wasi_errno_t { @@ -931,7 +931,7 @@ pub fn fd_prestat_get( } pub fn fd_prestat_dir_name( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, @@ -993,7 +993,7 @@ pub fn fd_prestat_dir_name( /// - `u32 *nwritten` /// Number of bytes written pub fn fd_pwrite( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, M>, iovs_len: M::Offset, @@ -1104,7 +1104,7 @@ pub fn fd_pwrite( /// Number of bytes read /// pub fn fd_read( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, M>, iovs_len: M::Offset, @@ -1263,7 +1263,7 @@ pub fn fd_read( /// The Number of bytes stored in `buf`; if less than `buf_len` then entire /// directory has been read pub fn fd_readdir( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, buf: WasmPtr, buf_len: M::Offset, @@ -1392,7 +1392,7 @@ pub fn fd_readdir( /// - `__wasi_fd_t to` /// Location to copy file descriptor to pub fn fd_renumber( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, from: __wasi_fd_t, to: __wasi_fd_t, ) -> __wasi_errno_t { @@ -1423,7 +1423,7 @@ pub fn fd_renumber( /// - `__wasi_fd_t fd` /// The new file handle that is a duplicate of the original pub fn fd_dup( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, ret_fd: WasmPtr<__wasi_fd_t, M>, ) -> __wasi_errno_t { @@ -1441,7 +1441,7 @@ pub fn fd_dup( /// ### `fd_event()` /// Creates a file handle for event notifications pub fn fd_event( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, initial_val: u64, flags: __wasi_eventfdflags, ret_fd: WasmPtr<__wasi_fd_t, M>, @@ -1484,7 +1484,7 @@ pub fn fd_event( /// - `__wasi_filesize_t *fd` /// The new offset relative to the start of the file pub fn fd_seek( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, @@ -1567,7 +1567,7 @@ pub fn fd_seek( /// TODO: figure out which errors this should return /// - `__WASI_EPERM` /// - `__WASI_ENOTCAPABLE` -pub fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub fn fd_sync(ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { debug!("wasi::fd_sync"); debug!("=> fd={}", fd); let env = ctx.data(); @@ -1610,7 +1610,7 @@ pub fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t /// - `__wasi_filesize_t *offset` /// The offset of `fd` relative to the start of the file pub fn fd_tell( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, M>, ) -> __wasi_errno_t { @@ -1645,7 +1645,7 @@ pub fn fd_tell( /// Errors: /// pub fn fd_write( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, M>, iovs_len: M::Offset, @@ -1781,7 +1781,7 @@ pub fn fd_write( /// - `__wasi_fd_t` /// Second file handle that represents the other end of the pipe pub fn fd_pipe( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ro_fd1: WasmPtr<__wasi_fd_t, M>, ro_fd2: WasmPtr<__wasi_fd_t, M>, ) -> __wasi_errno_t { @@ -1829,7 +1829,7 @@ pub fn fd_pipe( /// - __WASI_RIGHT_PATH_CREATE_DIRECTORY /// This right must be set on the directory that the file is created in (TODO: verify that this is true) pub fn path_create_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, @@ -1957,7 +1957,7 @@ pub fn path_create_directory( /// - `__wasi_file_stat_t *buf` /// The location where the metadata will be stored pub fn path_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -2045,7 +2045,7 @@ pub fn path_filestat_get_internal( /// - `__wasi_fstflags_t fst_flags` /// A bitmask controlling which attributes are set pub fn path_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -2123,7 +2123,7 @@ pub fn path_filestat_set_times( /// - `u32 old_path_len` /// Length of the `new_path` string pub fn path_link( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -2219,7 +2219,7 @@ pub fn path_link( /// Possible Errors: /// - `__WASI_EACCES`, `__WASI_EBADF`, `__WASI_EFAULT`, `__WASI_EFBIG?`, `__WASI_EINVAL`, `__WASI_EIO`, `__WASI_ELOOP`, `__WASI_EMFILE`, `__WASI_ENAMETOOLONG?`, `__WASI_ENFILE`, `__WASI_ENOENT`, `__WASI_ENOTDIR`, `__WASI_EROFS`, and `__WASI_ENOTCAPABLE` pub fn path_open( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -2462,7 +2462,7 @@ pub fn path_open( /// - `u32 buf_used` /// The number of bytes written to `buf` pub fn path_readlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, @@ -2513,7 +2513,7 @@ pub fn path_readlink( /// Returns __WASI_ENOTEMTPY if directory is not empty pub fn path_remove_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, @@ -2598,7 +2598,7 @@ pub fn path_remove_directory( /// - `u32 new_path_len` /// The number of bytes to read from `new_path` pub fn path_rename( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: M::Offset, @@ -2762,7 +2762,7 @@ pub fn path_rename( /// - `u32 new_path_len` /// The number of bytes to read from `new_path` pub fn path_symlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, old_path: WasmPtr, old_path_len: M::Offset, fd: __wasi_fd_t, @@ -2862,7 +2862,7 @@ pub fn path_symlink( /// - `u32 path_len` /// The number of bytes in the `path` array pub fn path_unlink_file( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, fd: __wasi_fd_t, path: WasmPtr, path_len: M::Offset, @@ -2973,7 +2973,7 @@ pub fn path_unlink_file( /// - `u32 nevents` /// The number of events seen pub fn poll_oneoff( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, in_: WasmPtr<__wasi_subscription_t, M>, out_: WasmPtr<__wasi_event_t, M>, nsubscriptions: M::Offset, @@ -3223,7 +3223,10 @@ pub fn poll_oneoff( /// Inputs: /// - `__wasi_exitcode_t` /// Exit code to return to the operating system -pub fn proc_exit(ctx: ContextMut<'_, WasiEnv>, code: __wasi_exitcode_t) -> Result<(), WasiError> { +pub fn proc_exit( + ctx: FunctionEnvMut<'_, WasiEnv>, + code: __wasi_exitcode_t, +) -> Result<(), WasiError> { debug!("wasi::proc_exit, {}", code); Err(WasiError::Exit(code)) } @@ -3234,14 +3237,14 @@ pub fn proc_exit(ctx: ContextMut<'_, WasiEnv>, code: __wasi_exitcode_t) -> Resul /// Inputs: /// - `__wasi_signal_t` /// Signal to be raised for this process -pub fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { +pub fn proc_raise(ctx: FunctionEnvMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { debug!("wasi::proc_raise"); unimplemented!("wasi::proc_raise") } /// ### `sched_yield()` /// Yields execution of the thread -pub fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { +pub fn sched_yield(ctx: FunctionEnvMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { trace!("wasi::sched_yield"); let env = ctx.data(); env.yield_now()?; @@ -3256,7 +3259,7 @@ pub fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiE /// - `size_t buf_len` /// The number of bytes that will be written pub fn random_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, buf: WasmPtr, buf_len: M::Offset, ) -> __wasi_errno_t { @@ -3279,7 +3282,7 @@ pub fn random_get( /// ### `tty_get()` /// Retrieves the current state of the TTY pub fn tty_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, M>, ) -> __wasi_errno_t { debug!("wasi::tty_stdin"); @@ -3322,7 +3325,7 @@ pub fn tty_get( /// ### `tty_set()` /// Updates the properties of the rect pub fn tty_set( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, tty_state: WasmPtr<__wasi_tty_t, M>, ) -> __wasi_errno_t { debug!("wasi::tty_set"); @@ -3372,7 +3375,7 @@ pub fn tty_set( /// If the path exceeds the size of the buffer then this function /// will fill the path_len with the needed size and return EOVERFLOW pub fn getcwd( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, path: WasmPtr, path_len: WasmPtr, ) -> __wasi_errno_t { @@ -3413,7 +3416,7 @@ pub fn getcwd( /// ### `chdir()` /// Sets the current working directory pub fn chdir( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, path: WasmPtr, path_len: M::Offset, ) -> __wasi_errno_t { @@ -3445,7 +3448,7 @@ pub fn chdir( /// Returns the thread index of the newly created thread /// (indices always start from zero) pub fn thread_spawn( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, method: WasmPtr, method_len: M::Offset, user_data: u64, @@ -3532,7 +3535,7 @@ pub fn thread_spawn( /// /// * `duration` - Amount of time that the thread should sleep pub fn thread_sleep( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, duration: __wasi_timestamp_t, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::thread_sleep"); @@ -3547,7 +3550,7 @@ pub fn thread_sleep( /// Returns the index of the current thread /// (threads indices are sequencial from zero) pub fn thread_id( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ret_tid: WasmPtr<__wasi_tid_t, M>, ) -> __wasi_errno_t { debug!("wasi::thread_id"); @@ -3566,7 +3569,7 @@ pub fn thread_id( /// /// * `tid` - Handle of the thread to wait on pub fn thread_join( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, tid: __wasi_tid_t, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::thread_join"); @@ -3594,7 +3597,7 @@ pub fn thread_join( /// Returns the available parallelism which is normally the /// number of available cores that can run concurrently pub fn thread_parallelism( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ret_parallelism: WasmPtr, ) -> __wasi_errno_t { debug!("wasi::thread_parallelism"); @@ -3612,7 +3615,7 @@ pub fn thread_parallelism( /// ### `getpid()` /// Returns the handle of the current process pub fn getpid( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ret_pid: WasmPtr<__wasi_pid_t, M>, ) -> __wasi_errno_t { debug!("wasi::getpid"); @@ -3637,7 +3640,7 @@ pub fn getpid( /// /// * `rval` - The exit code returned by the process. pub fn thread_exit( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, exitcode: __wasi_exitcode_t, ) -> Result<__wasi_errno_t, WasiError> { debug!("wasi::thread_exit"); @@ -3664,7 +3667,7 @@ pub fn thread_exit( /// /// Returns a bus process id that can be used to invoke calls pub fn process_spawn( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, chroot: __wasi_bool_t, @@ -3765,7 +3768,7 @@ pub fn process_spawn( /// /// Returns a bus process id that can be used to invoke calls pub fn bus_open_local( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, reuse: __wasi_bool_t, @@ -3796,7 +3799,7 @@ pub fn bus_open_local( /// /// Returns a bus process id that can be used to invoke calls pub fn bus_open_remote( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, name: WasmPtr, name_len: M::Offset, reuse: __wasi_bool_t, @@ -3822,7 +3825,7 @@ pub fn bus_open_remote( } fn bus_open_local_internal( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, name: String, reuse: bool, instance: Option, @@ -3884,7 +3887,7 @@ fn bus_open_local_internal( /// ## Parameters /// /// * `bid` - Handle of the bus process handle to be closed -pub fn bus_close(ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { +pub fn bus_close(ctx: FunctionEnvMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { trace!("wasi::bus_close (bid={})", bid); let bid: WasiBusProcessId = bid.into(); @@ -3907,7 +3910,7 @@ pub fn bus_close(ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno /// * `format` - Format of the data pushed onto the bus /// * `buf` - The buffer where data to be transmitted is stored pub fn bus_call( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, bid: __wasi_bid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -3944,7 +3947,7 @@ pub fn bus_call( /// * `format` - Format of the data pushed onto the bus /// * `buf` - The buffer where data to be transmitted is stored pub fn bus_subcall( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, parent: __wasi_cid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -3984,7 +3987,7 @@ pub fn bus_subcall( /// /// Returns the number of events that have occured pub fn bus_poll( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, timeout: __wasi_timestamp_t, events: WasmPtr, nevents: M::Offset, @@ -4012,7 +4015,7 @@ pub fn bus_poll( /// * `format` - Format of the data pushed onto the bus /// * `buf` - The buffer where data to be transmitted is stored pub fn call_reply( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t, format: __wasi_busdataformat_t, buf: WasmPtr, @@ -4039,7 +4042,7 @@ pub fn call_reply( /// * `cid` - Handle of the call to raise a fault on /// * `fault` - Fault to be raised on the bus pub fn call_fault( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t, fault: __bus_errno_t, ) -> __bus_errno_t { @@ -4055,7 +4058,7 @@ pub fn call_fault( /// ## Parameters /// /// * `cid` - Handle of the bus call handle to be dropped -pub fn call_close(ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { +pub fn call_close(ctx: FunctionEnvMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { let env = ctx.data(); let bus = env.runtime.bus(); trace!("wasi::call_close (cid={})", cid); @@ -4074,7 +4077,7 @@ pub fn call_close(ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errn /// /// Returns a socket handle which is used to send and receive data pub fn ws_connect( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, url: WasmPtr, url_len: M::Offset, ret_sock: WasmPtr<__wasi_fd_t, M>, @@ -4126,7 +4129,7 @@ pub fn ws_connect( /// The body of the response can be streamed from the returned /// file handle pub fn http_request( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, url: WasmPtr, url_len: M::Offset, method: WasmPtr, @@ -4233,7 +4236,7 @@ pub fn http_request( /// * `status` - Pointer to a buffer that will be filled with the current /// status of this HTTP request pub fn http_status( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, status: WasmPtr<__wasi_http_status_t, M>, ) -> __wasi_errno_t { @@ -4272,7 +4275,7 @@ pub fn http_status( /// * `token` - Access token used to authenticate with the network /// * `security` - Level of encryption to encapsulate the network connection with pub fn port_bridge( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, network: WasmPtr, network_len: M::Offset, token: WasmPtr, @@ -4301,7 +4304,7 @@ pub fn port_bridge( /// ### `port_unbridge()` /// Disconnects from a remote network -pub fn port_unbridge(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub fn port_unbridge(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_unbridge"); let env = ctx.data(); wasi_try!(env.net().unbridge().map_err(net_error_into_wasi_err)); @@ -4310,7 +4313,7 @@ pub fn port_unbridge(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { /// ### `port_dhcp_acquire()` /// Acquires a set of IP addresses using DHCP -pub fn port_dhcp_acquire(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub fn port_dhcp_acquire(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_dhcp_acquire"); let env = ctx.data(); wasi_try!(env.net().dhcp_acquire().map_err(net_error_into_wasi_err)); @@ -4324,7 +4327,7 @@ pub fn port_dhcp_acquire(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { /// /// * `addr` - Address to be added pub fn port_addr_add( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_cidr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_addr_add"); @@ -4345,7 +4348,7 @@ pub fn port_addr_add( /// /// * `addr` - Address to be removed pub fn port_addr_remove( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_addr_remove"); @@ -4358,7 +4361,7 @@ pub fn port_addr_remove( /// ### `port_addr_clear()` /// Clears all the addresses on the local port -pub fn port_addr_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub fn port_addr_clear(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_addr_clear"); let env = ctx.data(); wasi_try!(env.net().ip_clear().map_err(net_error_into_wasi_err)); @@ -4368,7 +4371,7 @@ pub fn port_addr_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { /// ### `port_mac()` /// Returns the MAC address of the local port pub fn port_mac( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ret_mac: WasmPtr<__wasi_hardwareaddress_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_mac"); @@ -4394,7 +4397,7 @@ pub fn port_mac( /// /// The number of addresses returned. pub fn port_addr_list( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, addrs: WasmPtr<__wasi_cidr_t, M>, naddrs: WasmPtr, ) -> __wasi_errno_t { @@ -4429,7 +4432,7 @@ pub fn port_addr_list( /// /// * `addr` - Address of the default gateway pub fn port_gateway_set( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_gateway_set"); @@ -4444,7 +4447,7 @@ pub fn port_gateway_set( /// ### `port_route_add()` /// Adds a new route to the local port pub fn port_route_add( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, cidr: WasmPtr<__wasi_cidr_t, M>, via_router: WasmPtr<__wasi_addr_t, M>, preferred_until: WasmPtr<__wasi_option_timestamp_t, M>, @@ -4478,7 +4481,7 @@ pub fn port_route_add( /// ### `port_route_remove()` /// Removes an existing route from the local port pub fn port_route_remove( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, ip: WasmPtr<__wasi_addr_t, M>, ) -> __wasi_errno_t { debug!("wasi::port_route_remove"); @@ -4491,7 +4494,7 @@ pub fn port_route_remove( /// ### `port_route_clear()` /// Clears all the routes in the local port -pub fn port_route_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub fn port_route_clear(ctx: FunctionEnvMut<'_, WasiEnv>) -> __wasi_errno_t { debug!("wasi::port_route_clear"); let env = ctx.data(); wasi_try!(env.net().route_clear().map_err(net_error_into_wasi_err)); @@ -4508,7 +4511,7 @@ pub fn port_route_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { /// /// * `routes` - The buffer where routes will be stored pub fn port_route_list( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, routes: WasmPtr<__wasi_route_t, M>, nroutes: WasmPtr, ) -> __wasi_errno_t { @@ -4551,7 +4554,7 @@ pub fn port_route_list( /// /// * `how` - Which channels on the socket to shut down. pub fn sock_shutdown( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, how: __wasi_sdflags_t, ) -> __wasi_errno_t { @@ -4578,7 +4581,7 @@ pub fn sock_shutdown( /// ### `sock_status()` /// Returns the current status of a socket pub fn sock_status( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_status: WasmPtr<__wasi_sockstatus_t, M>, ) -> __wasi_errno_t { @@ -4612,7 +4615,7 @@ pub fn sock_status( /// /// * `fd` - Socket that the address is bound to pub fn sock_addr_local( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, ret_addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { @@ -4644,7 +4647,7 @@ pub fn sock_addr_local( /// /// * `fd` - Socket that the address is bound to pub fn sock_addr_peer( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, ro_addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { @@ -4682,7 +4685,7 @@ pub fn sock_addr_peer( /// /// The file descriptor of the socket that has been opened. pub fn sock_open( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, af: __wasi_addressfamily_t, ty: __wasi_socktype_t, pt: __wasi_sockproto_t, @@ -4738,7 +4741,7 @@ pub fn sock_open( /// * `sockopt` - Socket option to be set /// * `flag` - Value to set the option to pub fn sock_set_opt_flag( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, flag: __wasi_bool_t, @@ -4767,7 +4770,7 @@ pub fn sock_set_opt_flag( /// * `fd` - Socket descriptor /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_flag( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_flag: WasmPtr<__wasi_bool_t, M>, @@ -4799,7 +4802,7 @@ pub fn sock_get_opt_flag( /// * `sockopt` - Socket option to be set /// * `time` - Value to set the time to pub fn sock_set_opt_time( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, time: WasmPtr<__wasi_option_timestamp_t, M>, @@ -4839,7 +4842,7 @@ pub fn sock_set_opt_time( /// * `fd` - Socket descriptor /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_time( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_time: WasmPtr<__wasi_option_timestamp_t, M>, @@ -4886,7 +4889,7 @@ pub fn sock_get_opt_time( /// * `opt` - Socket option to be set /// * `size` - Buffer size pub fn sock_set_opt_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, size: __wasi_filesize_t, @@ -4924,7 +4927,7 @@ pub fn sock_set_opt_size( /// * `fd` - Socket descriptor /// * `sockopt` - Socket option to be retrieved pub fn sock_get_opt_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_size: WasmPtr<__wasi_filesize_t, M>, @@ -4962,7 +4965,7 @@ pub fn sock_get_opt_size( /// * `multiaddr` - Multicast group to joined /// * `interface` - Interface that will join pub fn sock_join_multicast_v4( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, M>, iface: WasmPtr<__wasi_addr_ip4_t, M>, @@ -4988,7 +4991,7 @@ pub fn sock_join_multicast_v4( /// * `multiaddr` - Multicast group to leave /// * `interface` - Interface that will left pub fn sock_leave_multicast_v4( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, M>, iface: WasmPtr<__wasi_addr_ip4_t, M>, @@ -5014,7 +5017,7 @@ pub fn sock_leave_multicast_v4( /// * `multiaddr` - Multicast group to joined /// * `interface` - Interface that will join pub fn sock_join_multicast_v6( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, M>, iface: u32, @@ -5039,7 +5042,7 @@ pub fn sock_join_multicast_v6( /// * `multiaddr` - Multicast group to leave /// * `interface` - Interface that will left pub fn sock_leave_multicast_v6( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, M>, iface: u32, @@ -5064,7 +5067,7 @@ pub fn sock_leave_multicast_v6( /// * `fd` - File descriptor of the socket to be bind /// * `addr` - Address to bind the socket to pub fn sock_bind( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { @@ -5095,7 +5098,7 @@ pub fn sock_bind( /// * `fd` - File descriptor of the socket to be bind /// * `backlog` - Maximum size of the queue for pending connections pub fn sock_listen( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, backlog: M::Offset, ) -> __wasi_errno_t { @@ -5125,7 +5128,7 @@ pub fn sock_listen( /// /// New socket connection pub fn sock_accept( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, fd_flags: __wasi_fdflags_t, ro_fd: WasmPtr<__wasi_fd_t, M>, @@ -5201,7 +5204,7 @@ pub fn sock_accept( /// * `fd` - Socket descriptor /// * `addr` - Address of the socket to connect to pub fn sock_connect( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, M>, ) -> __wasi_errno_t { @@ -5233,7 +5236,7 @@ pub fn sock_connect( /// /// Number of bytes stored in ri_data and message flags. pub fn sock_recv( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, M>, ri_data_len: M::Offset, @@ -5275,7 +5278,7 @@ pub fn sock_recv( /// /// Number of bytes stored in ri_data and message flags. pub fn sock_recv_from( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, M>, ri_data_len: M::Offset, @@ -5318,7 +5321,7 @@ pub fn sock_recv_from( /// /// Number of bytes transmitted. pub fn sock_send( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, M>, si_data_len: M::Offset, @@ -5360,7 +5363,7 @@ pub fn sock_send( /// /// Number of bytes transmitted. pub fn sock_send_to( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, M>, si_data_len: M::Offset, @@ -5401,7 +5404,7 @@ pub fn sock_send_to( /// /// Number of bytes transmitted. pub unsafe fn sock_send_file( - mut ctx: ContextMut<'_, WasiEnv>, + mut ctx: FunctionEnvMut<'_, WasiEnv>, sock: __wasi_fd_t, in_fd: __wasi_fd_t, offset: __wasi_filesize_t, @@ -5534,7 +5537,7 @@ pub unsafe fn sock_send_file( /// /// The number of IP addresses returned during the DNS resolution. pub fn resolve( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut<'_, WasiEnv>, host: WasmPtr, host_len: M::Offset, port: u16, diff --git a/lib/wasi/src/syscalls/wasi.rs b/lib/wasi/src/syscalls/wasi.rs index 14ab2200bbc..b2575f6e53c 100644 --- a/lib/wasi/src/syscalls/wasi.rs +++ b/lib/wasi/src/syscalls/wasi.rs @@ -1,13 +1,13 @@ #![deny(dead_code)] use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{ContextMut, Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{StoreMut, Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; use wasmer_wasi_types::*; type MemoryType = Memory32; type MemoryOffset = u32; pub(crate) fn args_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, argv: WasmPtr, MemoryType>, argv_buf: WasmPtr, ) -> __wasi_errno_t { @@ -15,7 +15,7 @@ pub(crate) fn args_get( } pub(crate) fn args_sizes_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -23,7 +23,7 @@ pub(crate) fn args_sizes_get( } pub(crate) fn clock_res_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { @@ -31,7 +31,7 @@ pub(crate) fn clock_res_get( } pub(crate) fn clock_time_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, MemoryType>, @@ -40,7 +40,7 @@ pub(crate) fn clock_time_get( } pub(crate) fn environ_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, environ: WasmPtr, MemoryType>, environ_buf: WasmPtr, ) -> __wasi_errno_t { @@ -48,7 +48,7 @@ pub(crate) fn environ_get( } pub(crate) fn environ_sizes_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -56,7 +56,7 @@ pub(crate) fn environ_sizes_get( } pub(crate) fn fd_advise( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -66,7 +66,7 @@ pub(crate) fn fd_advise( } pub(crate) fn fd_allocate( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -74,16 +74,16 @@ pub(crate) fn fd_allocate( super::fd_allocate(ctx, fd, offset, len) } -pub(crate) fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_close(ctx, fd) } -pub(crate) fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_datasync(ctx, fd) } pub(crate) fn fd_fdstat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, ) -> __wasi_errno_t { @@ -91,7 +91,7 @@ pub(crate) fn fd_fdstat_get( } pub(crate) fn fd_fdstat_set_flags( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { @@ -99,7 +99,7 @@ pub(crate) fn fd_fdstat_set_flags( } pub(crate) fn fd_fdstat_set_rights( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, @@ -108,7 +108,7 @@ pub(crate) fn fd_fdstat_set_rights( } pub(crate) fn fd_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { @@ -116,7 +116,7 @@ pub(crate) fn fd_filestat_get( } pub(crate) fn fd_filestat_set_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { @@ -124,7 +124,7 @@ pub(crate) fn fd_filestat_set_size( } pub(crate) fn fd_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, @@ -134,7 +134,7 @@ pub(crate) fn fd_filestat_set_times( } pub(crate) fn fd_pread( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -145,7 +145,7 @@ pub(crate) fn fd_pread( } pub(crate) fn fd_prestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, MemoryType>, ) -> __wasi_errno_t { @@ -153,7 +153,7 @@ pub(crate) fn fd_prestat_get( } pub(crate) fn fd_prestat_dir_name( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -162,7 +162,7 @@ pub(crate) fn fd_prestat_dir_name( } pub(crate) fn fd_pwrite( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -173,7 +173,7 @@ pub(crate) fn fd_pwrite( } pub(crate) fn fd_read( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -183,7 +183,7 @@ pub(crate) fn fd_read( } pub(crate) fn fd_readdir( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr, buf_len: MemoryOffset, @@ -194,7 +194,7 @@ pub(crate) fn fd_readdir( } pub(crate) fn fd_renumber( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, from: __wasi_fd_t, to: __wasi_fd_t, ) -> __wasi_errno_t { @@ -202,7 +202,7 @@ pub(crate) fn fd_renumber( } pub(crate) fn fd_seek( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, @@ -211,12 +211,12 @@ pub(crate) fn fd_seek( super::fd_seek::(ctx, fd, offset, whence, newoffset) } -pub(crate) fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_sync(ctx, fd) } pub(crate) fn fd_tell( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { @@ -224,7 +224,7 @@ pub(crate) fn fd_tell( } pub(crate) fn fd_write( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -234,7 +234,7 @@ pub(crate) fn fd_write( } pub(crate) fn path_create_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -243,7 +243,7 @@ pub(crate) fn path_create_directory( } pub(crate) fn path_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -254,7 +254,7 @@ pub(crate) fn path_filestat_get( } pub(crate) fn path_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -269,7 +269,7 @@ pub(crate) fn path_filestat_set_times( } pub(crate) fn path_link( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -291,7 +291,7 @@ pub(crate) fn path_link( } pub(crate) fn path_open( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -317,7 +317,7 @@ pub(crate) fn path_open( } pub(crate) fn path_readlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -329,7 +329,7 @@ pub(crate) fn path_readlink( } pub(crate) fn path_remove_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -338,7 +338,7 @@ pub(crate) fn path_remove_directory( } pub(crate) fn path_rename( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: MemoryOffset, @@ -358,7 +358,7 @@ pub(crate) fn path_rename( } pub(crate) fn path_symlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_path: WasmPtr, old_path_len: MemoryOffset, fd: __wasi_fd_t, @@ -369,7 +369,7 @@ pub(crate) fn path_symlink( } pub(crate) fn path_unlink_file( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -378,7 +378,7 @@ pub(crate) fn path_unlink_file( } pub(crate) fn poll_oneoff( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, in_: WasmPtr<__wasi_subscription_t, MemoryType>, out_: WasmPtr<__wasi_event_t, MemoryType>, nsubscriptions: MemoryOffset, @@ -388,30 +388,30 @@ pub(crate) fn poll_oneoff( } pub(crate) fn proc_exit( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, code: __wasi_exitcode_t, ) -> Result<(), WasiError> { super::proc_exit(ctx, code) } -pub(crate) fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { +pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: __wasi_signal_t) -> __wasi_errno_t { super::proc_raise(ctx, sig) } pub(crate) fn random_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, buf: WasmPtr, buf_len: MemoryOffset, ) -> __wasi_errno_t { super::random_get::(ctx, buf, buf_len) } -pub(crate) fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { +pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result<__wasi_errno_t, WasiError> { super::sched_yield(ctx) } pub(crate) fn sock_recv( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -431,7 +431,7 @@ pub(crate) fn sock_recv( } pub(crate) fn sock_send( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, @@ -442,7 +442,7 @@ pub(crate) fn sock_send( } pub(crate) fn sock_shutdown( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, how: __wasi_sdflags_t, ) -> __wasi_errno_t { diff --git a/lib/wasi/src/syscalls/wasix32.rs b/lib/wasi/src/syscalls/wasix32.rs index 712c1a34eb9..5cb6899c3ef 100644 --- a/lib/wasi/src/syscalls/wasix32.rs +++ b/lib/wasi/src/syscalls/wasix32.rs @@ -1,13 +1,13 @@ #![deny(dead_code)] use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{ContextMut, Memory, Memory32, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{FunctionEnvMut, Memory, Memory32, MemorySize, StoreMut, WasmPtr, WasmSlice}; use wasmer_wasi_types::*; type MemoryType = Memory32; type MemoryOffset = u32; pub(crate) fn args_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, argv: WasmPtr, MemoryType>, argv_buf: WasmPtr, ) -> __wasi_errno_t { @@ -15,7 +15,7 @@ pub(crate) fn args_get( } pub(crate) fn args_sizes_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -23,7 +23,7 @@ pub(crate) fn args_sizes_get( } pub(crate) fn clock_res_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { @@ -31,7 +31,7 @@ pub(crate) fn clock_res_get( } pub(crate) fn clock_time_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, MemoryType>, @@ -40,7 +40,7 @@ pub(crate) fn clock_time_get( } pub(crate) fn environ_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, environ: WasmPtr, MemoryType>, environ_buf: WasmPtr, ) -> __wasi_errno_t { @@ -48,7 +48,7 @@ pub(crate) fn environ_get( } pub(crate) fn environ_sizes_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -56,7 +56,7 @@ pub(crate) fn environ_sizes_get( } pub(crate) fn fd_advise( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -66,7 +66,7 @@ pub(crate) fn fd_advise( } pub(crate) fn fd_allocate( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -74,16 +74,16 @@ pub(crate) fn fd_allocate( super::fd_allocate(ctx, fd, offset, len) } -pub(crate) fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_close(ctx, fd) } -pub(crate) fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_datasync(ctx, fd) } pub(crate) fn fd_fdstat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, ) -> __wasi_errno_t { @@ -91,7 +91,7 @@ pub(crate) fn fd_fdstat_get( } pub(crate) fn fd_fdstat_set_flags( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { @@ -99,7 +99,7 @@ pub(crate) fn fd_fdstat_set_flags( } pub(crate) fn fd_fdstat_set_rights( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, @@ -108,7 +108,7 @@ pub(crate) fn fd_fdstat_set_rights( } pub(crate) fn fd_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { @@ -116,7 +116,7 @@ pub(crate) fn fd_filestat_get( } pub(crate) fn fd_filestat_set_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { @@ -124,7 +124,7 @@ pub(crate) fn fd_filestat_set_size( } pub(crate) fn fd_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, @@ -134,7 +134,7 @@ pub(crate) fn fd_filestat_set_times( } pub(crate) fn fd_pread( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -145,7 +145,7 @@ pub(crate) fn fd_pread( } pub(crate) fn fd_prestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, MemoryType>, ) -> __wasi_errno_t { @@ -153,7 +153,7 @@ pub(crate) fn fd_prestat_get( } pub(crate) fn fd_prestat_dir_name( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -162,7 +162,7 @@ pub(crate) fn fd_prestat_dir_name( } pub(crate) fn fd_pwrite( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -173,7 +173,7 @@ pub(crate) fn fd_pwrite( } pub(crate) fn fd_read( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -183,7 +183,7 @@ pub(crate) fn fd_read( } pub(crate) fn fd_readdir( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr, buf_len: MemoryOffset, @@ -194,7 +194,7 @@ pub(crate) fn fd_readdir( } pub(crate) fn fd_renumber( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, from: __wasi_fd_t, to: __wasi_fd_t, ) -> __wasi_errno_t { @@ -202,7 +202,7 @@ pub(crate) fn fd_renumber( } pub(crate) fn fd_seek( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, @@ -211,12 +211,12 @@ pub(crate) fn fd_seek( super::fd_seek::(ctx, fd, offset, whence, newoffset) } -pub(crate) fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_sync(ctx, fd) } pub(crate) fn fd_tell( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { @@ -224,7 +224,7 @@ pub(crate) fn fd_tell( } pub(crate) fn fd_write( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -234,7 +234,7 @@ pub(crate) fn fd_write( } pub(crate) fn path_create_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -243,7 +243,7 @@ pub(crate) fn path_create_directory( } pub(crate) fn path_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -254,7 +254,7 @@ pub(crate) fn path_filestat_get( } pub(crate) fn path_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -269,7 +269,7 @@ pub(crate) fn path_filestat_set_times( } pub(crate) fn path_link( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -291,7 +291,7 @@ pub(crate) fn path_link( } pub(crate) fn path_open( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -317,7 +317,7 @@ pub(crate) fn path_open( } pub(crate) fn path_readlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -329,7 +329,7 @@ pub(crate) fn path_readlink( } pub(crate) fn path_remove_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -338,7 +338,7 @@ pub(crate) fn path_remove_directory( } pub(crate) fn path_rename( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: MemoryOffset, @@ -358,7 +358,7 @@ pub(crate) fn path_rename( } pub(crate) fn path_symlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_path: WasmPtr, old_path_len: MemoryOffset, fd: __wasi_fd_t, @@ -369,7 +369,7 @@ pub(crate) fn path_symlink( } pub(crate) fn path_unlink_file( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -378,7 +378,7 @@ pub(crate) fn path_unlink_file( } pub(crate) fn poll_oneoff( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, in_: WasmPtr<__wasi_subscription_t, MemoryType>, out_: WasmPtr<__wasi_event_t, MemoryType>, nsubscriptions: MemoryOffset, @@ -388,18 +388,18 @@ pub(crate) fn poll_oneoff( } pub(crate) fn proc_exit( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, code: __wasi_exitcode_t, ) -> Result<(), WasiError> { super::proc_exit(ctx, code) } -pub(crate) fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { +pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: __wasi_signal_t) -> __wasi_errno_t { super::proc_raise(ctx, sig) } pub(crate) fn random_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, buf: WasmPtr, buf_len: MemoryOffset, ) -> __wasi_errno_t { @@ -407,7 +407,7 @@ pub(crate) fn random_get( } pub(crate) fn fd_dup( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { @@ -415,7 +415,7 @@ pub(crate) fn fd_dup( } pub(crate) fn fd_event( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, initial_val: u64, flags: __wasi_eventfdflags, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, @@ -424,7 +424,7 @@ pub(crate) fn fd_event( } pub(crate) fn fd_pipe( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ro_fd1: WasmPtr<__wasi_fd_t, MemoryType>, ro_fd2: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { @@ -432,21 +432,21 @@ pub(crate) fn fd_pipe( } pub(crate) fn tty_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { super::tty_get::(ctx, tty_state) } pub(crate) fn tty_set( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { super::tty_set::(ctx, tty_state) } pub(crate) fn getcwd( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, path: WasmPtr, path_len: WasmPtr, ) -> __wasi_errno_t { @@ -454,7 +454,7 @@ pub(crate) fn getcwd( } pub(crate) fn chdir( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { @@ -462,7 +462,7 @@ pub(crate) fn chdir( } pub(crate) fn thread_spawn( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, method: WasmPtr, method_len: MemoryOffset, user_data: u64, @@ -473,53 +473,53 @@ pub(crate) fn thread_spawn( } pub(crate) fn thread_sleep( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, duration: __wasi_timestamp_t, ) -> Result<__wasi_errno_t, WasiError> { super::thread_sleep(ctx, duration) } pub(crate) fn thread_id( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, ) -> __wasi_errno_t { super::thread_id::(ctx, ret_tid) } pub(crate) fn thread_join( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, tid: __wasi_tid_t, ) -> Result<__wasi_errno_t, WasiError> { super::thread_join(ctx, tid) } pub(crate) fn thread_parallelism( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_parallelism: WasmPtr, ) -> __wasi_errno_t { super::thread_parallelism::(ctx, ret_parallelism) } pub(crate) fn thread_exit( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, exitcode: __wasi_exitcode_t, ) -> Result<__wasi_errno_t, WasiError> { super::thread_exit(ctx, exitcode) } -pub(crate) fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { +pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result<__wasi_errno_t, WasiError> { super::sched_yield(ctx) } pub(crate) fn getpid( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_pid: WasmPtr<__wasi_pid_t, MemoryType>, ) -> __wasi_errno_t { super::getpid::(ctx, ret_pid) } pub(crate) fn process_spawn( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, name: WasmPtr, name_len: MemoryOffset, chroot: __wasi_bool_t, @@ -553,7 +553,7 @@ pub(crate) fn process_spawn( } pub(crate) fn bus_open_local( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, @@ -563,7 +563,7 @@ pub(crate) fn bus_open_local( } pub(crate) fn bus_open_remote( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, @@ -586,12 +586,12 @@ pub(crate) fn bus_open_remote( ) } -pub(crate) fn bus_close(ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { +pub(crate) fn bus_close(ctx: FunctionEnvMut, bid: __wasi_bid_t) -> __bus_errno_t { super::bus_close(ctx, bid) } pub(crate) fn bus_call( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, bid: __wasi_bid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -607,7 +607,7 @@ pub(crate) fn bus_call( } pub(crate) fn bus_subcall( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, parent: __wasi_cid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -623,7 +623,7 @@ pub(crate) fn bus_subcall( } pub(crate) fn bus_poll( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, timeout: __wasi_timestamp_t, events: WasmPtr, nevents: MemoryOffset, @@ -643,7 +643,7 @@ pub(crate) fn bus_poll( } pub(crate) fn call_reply( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, cid: __wasi_cid_t, format: __wasi_busdataformat_t, buf: WasmPtr, @@ -653,19 +653,19 @@ pub(crate) fn call_reply( } pub(crate) fn call_fault( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, cid: __wasi_cid_t, fault: __bus_errno_t, ) -> __bus_errno_t { super::call_fault(ctx, cid, fault) } -pub(crate) fn call_close(ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { +pub(crate) fn call_close(ctx: FunctionEnvMut, cid: __wasi_cid_t) -> __bus_errno_t { super::call_close(ctx, cid) } pub(crate) fn port_bridge( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, network: WasmPtr, network_len: MemoryOffset, token: WasmPtr, @@ -675,34 +675,34 @@ pub(crate) fn port_bridge( super::port_bridge::(ctx, network, network_len, token, token_len, security) } -pub(crate) fn port_unbridge(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_unbridge(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_unbridge(ctx) } -pub(crate) fn port_dhcp_acquire(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_dhcp_acquire(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_dhcp_acquire(ctx) } pub(crate) fn port_addr_add( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, addr: WasmPtr<__wasi_cidr_t, MemoryType>, ) -> __wasi_errno_t { super::port_addr_add::(ctx, addr) } pub(crate) fn port_addr_remove( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, addr: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { super::port_addr_remove::(ctx, addr) } -pub(crate) fn port_addr_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_addr_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_addr_clear(ctx) } pub(crate) fn port_addr_list( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, addrs: WasmPtr<__wasi_cidr_t, MemoryType>, naddrs: WasmPtr, ) -> __wasi_errno_t { @@ -710,21 +710,21 @@ pub(crate) fn port_addr_list( } pub(crate) fn port_mac( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, ) -> __wasi_errno_t { super::port_mac::(ctx, ret_mac) } pub(crate) fn port_gateway_set( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { super::port_gateway_set::(ctx, ip) } pub(crate) fn port_route_add( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, cidr: WasmPtr<__wasi_cidr_t, MemoryType>, via_router: WasmPtr<__wasi_addr_t, MemoryType>, preferred_until: WasmPtr<__wasi_option_timestamp_t, MemoryType>, @@ -734,18 +734,18 @@ pub(crate) fn port_route_add( } pub(crate) fn port_route_remove( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { super::port_route_remove::(ctx, ip) } -pub(crate) fn port_route_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_route_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_route_clear(ctx) } pub(crate) fn port_route_list( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, routes: WasmPtr<__wasi_route_t, MemoryType>, nroutes: WasmPtr, ) -> __wasi_errno_t { @@ -753,7 +753,7 @@ pub(crate) fn port_route_list( } pub(crate) fn ws_connect( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, url: WasmPtr, url_len: MemoryOffset, ret_sock: WasmPtr<__wasi_fd_t, MemoryType>, @@ -762,7 +762,7 @@ pub(crate) fn ws_connect( } pub(crate) fn http_request( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, url: WasmPtr, url_len: MemoryOffset, method: WasmPtr, @@ -786,7 +786,7 @@ pub(crate) fn http_request( } pub(crate) fn http_status( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, status: WasmPtr<__wasi_http_status_t, MemoryType>, status_text: WasmPtr, @@ -798,7 +798,7 @@ pub(crate) fn http_status( } pub(crate) fn sock_status( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ret_status: WasmPtr<__wasi_sockstatus_t, MemoryType>, ) -> __wasi_errno_t { @@ -806,7 +806,7 @@ pub(crate) fn sock_status( } pub(crate) fn sock_addr_local( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -814,7 +814,7 @@ pub(crate) fn sock_addr_local( } pub(crate) fn sock_addr_peer( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -822,7 +822,7 @@ pub(crate) fn sock_addr_peer( } pub(crate) fn sock_open( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, af: __wasi_addressfamily_t, ty: __wasi_socktype_t, pt: __wasi_sockproto_t, @@ -832,7 +832,7 @@ pub(crate) fn sock_open( } pub(crate) fn sock_set_opt_flag( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, flag: __wasi_bool_t, @@ -841,7 +841,7 @@ pub(crate) fn sock_set_opt_flag( } pub(crate) fn sock_get_opt_flag( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_flag: WasmPtr<__wasi_bool_t, MemoryType>, @@ -850,7 +850,7 @@ pub(crate) fn sock_get_opt_flag( } pub fn sock_set_opt_time( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, @@ -859,7 +859,7 @@ pub fn sock_set_opt_time( } pub fn sock_get_opt_time( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, @@ -868,7 +868,7 @@ pub fn sock_get_opt_time( } pub fn sock_set_opt_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, size: __wasi_filesize_t, @@ -877,7 +877,7 @@ pub fn sock_set_opt_size( } pub fn sock_get_opt_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_size: WasmPtr<__wasi_filesize_t, MemoryType>, @@ -886,7 +886,7 @@ pub fn sock_get_opt_size( } pub(crate) fn sock_join_multicast_v4( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, @@ -895,7 +895,7 @@ pub(crate) fn sock_join_multicast_v4( } pub(crate) fn sock_leave_multicast_v4( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, @@ -904,7 +904,7 @@ pub(crate) fn sock_leave_multicast_v4( } pub(crate) fn sock_join_multicast_v6( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, @@ -913,7 +913,7 @@ pub(crate) fn sock_join_multicast_v6( } pub(crate) fn sock_leave_multicast_v6( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, @@ -922,7 +922,7 @@ pub(crate) fn sock_leave_multicast_v6( } pub(crate) fn sock_bind( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -930,7 +930,7 @@ pub(crate) fn sock_bind( } pub(crate) fn sock_listen( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, backlog: MemoryOffset, ) -> __wasi_errno_t { @@ -938,7 +938,7 @@ pub(crate) fn sock_listen( } pub(crate) fn sock_accept( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, fd_flags: __wasi_fdflags_t, ro_fd: WasmPtr<__wasi_fd_t, MemoryType>, @@ -948,7 +948,7 @@ pub(crate) fn sock_accept( } pub(crate) fn sock_connect( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -956,7 +956,7 @@ pub(crate) fn sock_connect( } pub(crate) fn sock_recv( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -976,7 +976,7 @@ pub(crate) fn sock_recv( } pub(crate) fn sock_recv_from( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -998,7 +998,7 @@ pub(crate) fn sock_recv_from( } pub(crate) fn sock_send( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, @@ -1009,7 +1009,7 @@ pub(crate) fn sock_send( } pub(crate) fn sock_send_to( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, @@ -1029,7 +1029,7 @@ pub(crate) fn sock_send_to( } pub(crate) fn sock_send_file( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, out_fd: __wasi_fd_t, in_fd: __wasi_fd_t, offset: __wasi_filesize_t, @@ -1040,7 +1040,7 @@ pub(crate) fn sock_send_file( } pub(crate) fn sock_shutdown( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, how: __wasi_sdflags_t, ) -> __wasi_errno_t { @@ -1048,7 +1048,7 @@ pub(crate) fn sock_shutdown( } pub(crate) fn resolve( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, host: WasmPtr, host_len: MemoryOffset, port: u16, diff --git a/lib/wasi/src/syscalls/wasix64.rs b/lib/wasi/src/syscalls/wasix64.rs index 4064232ae6f..b42307e0da8 100644 --- a/lib/wasi/src/syscalls/wasix64.rs +++ b/lib/wasi/src/syscalls/wasix64.rs @@ -1,13 +1,13 @@ #![deny(dead_code)] use crate::{WasiEnv, WasiError, WasiState, WasiThread}; -use wasmer::{ContextMut, Memory, Memory64, MemorySize, WasmPtr, WasmSlice}; +use wasmer::{FunctionEnvMut, Memory, Memory64, MemorySize, StoreMut, WasmPtr, WasmSlice}; use wasmer_wasi_types::*; type MemoryType = Memory64; type MemoryOffset = u64; pub(crate) fn args_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, argv: WasmPtr, MemoryType>, argv_buf: WasmPtr, ) -> __wasi_errno_t { @@ -15,7 +15,7 @@ pub(crate) fn args_get( } pub(crate) fn args_sizes_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, argc: WasmPtr, argv_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -23,7 +23,7 @@ pub(crate) fn args_sizes_get( } pub(crate) fn clock_res_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, clock_id: __wasi_clockid_t, resolution: WasmPtr<__wasi_timestamp_t, MemoryType>, ) -> __wasi_errno_t { @@ -31,7 +31,7 @@ pub(crate) fn clock_res_get( } pub(crate) fn clock_time_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, clock_id: __wasi_clockid_t, precision: __wasi_timestamp_t, time: WasmPtr<__wasi_timestamp_t, MemoryType>, @@ -40,7 +40,7 @@ pub(crate) fn clock_time_get( } pub(crate) fn environ_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, environ: WasmPtr, MemoryType>, environ_buf: WasmPtr, ) -> __wasi_errno_t { @@ -48,7 +48,7 @@ pub(crate) fn environ_get( } pub(crate) fn environ_sizes_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, environ_count: WasmPtr, environ_buf_size: WasmPtr, ) -> __wasi_errno_t { @@ -56,7 +56,7 @@ pub(crate) fn environ_sizes_get( } pub(crate) fn fd_advise( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -66,7 +66,7 @@ pub(crate) fn fd_advise( } pub(crate) fn fd_allocate( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filesize_t, len: __wasi_filesize_t, @@ -74,16 +74,16 @@ pub(crate) fn fd_allocate( super::fd_allocate(ctx, fd, offset, len) } -pub(crate) fn fd_close(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_close(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_close(ctx, fd) } -pub(crate) fn fd_datasync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_datasync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_datasync(ctx, fd) } pub(crate) fn fd_fdstat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf_ptr: WasmPtr<__wasi_fdstat_t, MemoryType>, ) -> __wasi_errno_t { @@ -91,7 +91,7 @@ pub(crate) fn fd_fdstat_get( } pub(crate) fn fd_fdstat_set_flags( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_fdflags_t, ) -> __wasi_errno_t { @@ -99,7 +99,7 @@ pub(crate) fn fd_fdstat_set_flags( } pub(crate) fn fd_fdstat_set_rights( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, fs_rights_base: __wasi_rights_t, fs_rights_inheriting: __wasi_rights_t, @@ -108,7 +108,7 @@ pub(crate) fn fd_fdstat_set_rights( } pub(crate) fn fd_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr<__wasi_filestat_t, MemoryType>, ) -> __wasi_errno_t { @@ -116,7 +116,7 @@ pub(crate) fn fd_filestat_get( } pub(crate) fn fd_filestat_set_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, st_size: __wasi_filesize_t, ) -> __wasi_errno_t { @@ -124,7 +124,7 @@ pub(crate) fn fd_filestat_set_size( } pub(crate) fn fd_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, st_atim: __wasi_timestamp_t, st_mtim: __wasi_timestamp_t, @@ -134,7 +134,7 @@ pub(crate) fn fd_filestat_set_times( } pub(crate) fn fd_pread( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -145,7 +145,7 @@ pub(crate) fn fd_pread( } pub(crate) fn fd_prestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr<__wasi_prestat_t, MemoryType>, ) -> __wasi_errno_t { @@ -153,7 +153,7 @@ pub(crate) fn fd_prestat_get( } pub(crate) fn fd_prestat_dir_name( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -162,7 +162,7 @@ pub(crate) fn fd_prestat_dir_name( } pub(crate) fn fd_pwrite( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -173,7 +173,7 @@ pub(crate) fn fd_pwrite( } pub(crate) fn fd_read( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_iovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -183,7 +183,7 @@ pub(crate) fn fd_read( } pub(crate) fn fd_readdir( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, buf: WasmPtr, buf_len: MemoryOffset, @@ -194,7 +194,7 @@ pub(crate) fn fd_readdir( } pub(crate) fn fd_renumber( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, from: __wasi_fd_t, to: __wasi_fd_t, ) -> __wasi_errno_t { @@ -202,7 +202,7 @@ pub(crate) fn fd_renumber( } pub(crate) fn fd_seek( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: __wasi_filedelta_t, whence: __wasi_whence_t, @@ -211,12 +211,12 @@ pub(crate) fn fd_seek( super::fd_seek::(ctx, fd, offset, whence, newoffset) } -pub(crate) fn fd_sync(ctx: ContextMut<'_, WasiEnv>, fd: __wasi_fd_t) -> __wasi_errno_t { +pub(crate) fn fd_sync(ctx: FunctionEnvMut, fd: __wasi_fd_t) -> __wasi_errno_t { super::fd_sync(ctx, fd) } pub(crate) fn fd_tell( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, offset: WasmPtr<__wasi_filesize_t, MemoryType>, ) -> __wasi_errno_t { @@ -224,7 +224,7 @@ pub(crate) fn fd_tell( } pub(crate) fn fd_write( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, iovs: WasmPtr<__wasi_ciovec_t, MemoryType>, iovs_len: MemoryOffset, @@ -234,7 +234,7 @@ pub(crate) fn fd_write( } pub(crate) fn path_create_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -243,7 +243,7 @@ pub(crate) fn path_create_directory( } pub(crate) fn path_filestat_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -254,7 +254,7 @@ pub(crate) fn path_filestat_get( } pub(crate) fn path_filestat_set_times( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, flags: __wasi_lookupflags_t, path: WasmPtr, @@ -269,7 +269,7 @@ pub(crate) fn path_filestat_set_times( } pub(crate) fn path_link( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_fd: __wasi_fd_t, old_flags: __wasi_lookupflags_t, old_path: WasmPtr, @@ -291,7 +291,7 @@ pub(crate) fn path_link( } pub(crate) fn path_open( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, dirfd: __wasi_fd_t, dirflags: __wasi_lookupflags_t, path: WasmPtr, @@ -317,7 +317,7 @@ pub(crate) fn path_open( } pub(crate) fn path_readlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, dir_fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -329,7 +329,7 @@ pub(crate) fn path_readlink( } pub(crate) fn path_remove_directory( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -338,7 +338,7 @@ pub(crate) fn path_remove_directory( } pub(crate) fn path_rename( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_fd: __wasi_fd_t, old_path: WasmPtr, old_path_len: MemoryOffset, @@ -358,7 +358,7 @@ pub(crate) fn path_rename( } pub(crate) fn path_symlink( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, old_path: WasmPtr, old_path_len: MemoryOffset, fd: __wasi_fd_t, @@ -369,7 +369,7 @@ pub(crate) fn path_symlink( } pub(crate) fn path_unlink_file( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, path: WasmPtr, path_len: MemoryOffset, @@ -378,7 +378,7 @@ pub(crate) fn path_unlink_file( } pub(crate) fn poll_oneoff( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, in_: WasmPtr<__wasi_subscription_t, MemoryType>, out_: WasmPtr<__wasi_event_t, MemoryType>, nsubscriptions: MemoryOffset, @@ -388,18 +388,18 @@ pub(crate) fn poll_oneoff( } pub(crate) fn proc_exit( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, code: __wasi_exitcode_t, ) -> Result<(), WasiError> { super::proc_exit(ctx, code) } -pub(crate) fn proc_raise(ctx: ContextMut<'_, WasiEnv>, sig: __wasi_signal_t) -> __wasi_errno_t { +pub(crate) fn proc_raise(ctx: FunctionEnvMut, sig: __wasi_signal_t) -> __wasi_errno_t { super::proc_raise(ctx, sig) } pub(crate) fn random_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, buf: WasmPtr, buf_len: MemoryOffset, ) -> __wasi_errno_t { @@ -407,7 +407,7 @@ pub(crate) fn random_get( } pub(crate) fn fd_dup( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, fd: __wasi_fd_t, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { @@ -415,7 +415,7 @@ pub(crate) fn fd_dup( } pub(crate) fn fd_event( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, initial_val: u64, flags: __wasi_eventfdflags, ret_fd: WasmPtr<__wasi_fd_t, MemoryType>, @@ -424,7 +424,7 @@ pub(crate) fn fd_event( } pub(crate) fn fd_pipe( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ro_fd1: WasmPtr<__wasi_fd_t, MemoryType>, ro_fd2: WasmPtr<__wasi_fd_t, MemoryType>, ) -> __wasi_errno_t { @@ -432,21 +432,21 @@ pub(crate) fn fd_pipe( } pub(crate) fn tty_get( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { super::tty_get::(ctx, tty_state) } pub(crate) fn tty_set( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, tty_state: WasmPtr<__wasi_tty_t, MemoryType>, ) -> __wasi_errno_t { super::tty_set::(ctx, tty_state) } pub(crate) fn getcwd( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, path: WasmPtr, path_len: WasmPtr, ) -> __wasi_errno_t { @@ -454,7 +454,7 @@ pub(crate) fn getcwd( } pub(crate) fn chdir( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, path: WasmPtr, path_len: MemoryOffset, ) -> __wasi_errno_t { @@ -462,7 +462,7 @@ pub(crate) fn chdir( } pub(crate) fn thread_spawn( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, method: WasmPtr, method_len: MemoryOffset, user_data: u64, @@ -473,53 +473,53 @@ pub(crate) fn thread_spawn( } pub(crate) fn thread_sleep( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, duration: __wasi_timestamp_t, ) -> Result<__wasi_errno_t, WasiError> { super::thread_sleep(ctx, duration) } pub(crate) fn thread_id( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_tid: WasmPtr<__wasi_tid_t, MemoryType>, ) -> __wasi_errno_t { super::thread_id::(ctx, ret_tid) } pub(crate) fn thread_join( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, tid: __wasi_tid_t, ) -> Result<__wasi_errno_t, WasiError> { super::thread_join(ctx, tid) } pub(crate) fn thread_parallelism( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_parallelism: WasmPtr, ) -> __wasi_errno_t { super::thread_parallelism::(ctx, ret_parallelism) } pub(crate) fn thread_exit( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, exitcode: __wasi_exitcode_t, ) -> Result<__wasi_errno_t, WasiError> { super::thread_exit(ctx, exitcode) } -pub(crate) fn sched_yield(ctx: ContextMut<'_, WasiEnv>) -> Result<__wasi_errno_t, WasiError> { +pub(crate) fn sched_yield(ctx: FunctionEnvMut) -> Result<__wasi_errno_t, WasiError> { super::sched_yield(ctx) } pub(crate) fn getpid( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_pid: WasmPtr<__wasi_pid_t, MemoryType>, ) -> __wasi_errno_t { super::getpid::(ctx, ret_pid) } pub(crate) fn process_spawn( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, name: WasmPtr, name_len: MemoryOffset, chroot: __wasi_bool_t, @@ -553,7 +553,7 @@ pub(crate) fn process_spawn( } pub(crate) fn bus_open_local( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, @@ -563,7 +563,7 @@ pub(crate) fn bus_open_local( } pub(crate) fn bus_open_remote( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, name: WasmPtr, name_len: MemoryOffset, reuse: __wasi_bool_t, @@ -586,12 +586,12 @@ pub(crate) fn bus_open_remote( ) } -pub(crate) fn bus_close(ctx: ContextMut<'_, WasiEnv>, bid: __wasi_bid_t) -> __bus_errno_t { +pub(crate) fn bus_close(ctx: FunctionEnvMut, bid: __wasi_bid_t) -> __bus_errno_t { super::bus_close(ctx, bid) } pub(crate) fn bus_call( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, bid: __wasi_bid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -607,7 +607,7 @@ pub(crate) fn bus_call( } pub(crate) fn bus_subcall( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, parent: __wasi_cid_t, keep_alive: __wasi_bool_t, topic: WasmPtr, @@ -623,7 +623,7 @@ pub(crate) fn bus_subcall( } pub(crate) fn bus_poll( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, timeout: __wasi_timestamp_t, events: WasmPtr, nevents: MemoryOffset, @@ -643,7 +643,7 @@ pub(crate) fn bus_poll( } pub(crate) fn call_reply( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, cid: __wasi_cid_t, format: __wasi_busdataformat_t, buf: WasmPtr, @@ -653,19 +653,19 @@ pub(crate) fn call_reply( } pub(crate) fn call_fault( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, cid: __wasi_cid_t, fault: __bus_errno_t, ) -> __bus_errno_t { super::call_fault(ctx, cid, fault) } -pub(crate) fn call_close(ctx: ContextMut<'_, WasiEnv>, cid: __wasi_cid_t) -> __bus_errno_t { +pub(crate) fn call_close(ctx: FunctionEnvMut, cid: __wasi_cid_t) -> __bus_errno_t { super::call_close(ctx, cid) } pub(crate) fn port_bridge( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, network: WasmPtr, network_len: MemoryOffset, token: WasmPtr, @@ -675,34 +675,34 @@ pub(crate) fn port_bridge( super::port_bridge::(ctx, network, network_len, token, token_len, security) } -pub(crate) fn port_unbridge(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_unbridge(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_unbridge(ctx) } -pub(crate) fn port_dhcp_acquire(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_dhcp_acquire(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_dhcp_acquire(ctx) } pub(crate) fn port_addr_add( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, addr: WasmPtr<__wasi_cidr_t, MemoryType>, ) -> __wasi_errno_t { super::port_addr_add::(ctx, addr) } pub(crate) fn port_addr_remove( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, addr: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { super::port_addr_remove::(ctx, addr) } -pub(crate) fn port_addr_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_addr_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_addr_clear(ctx) } pub(crate) fn port_addr_list( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, addrs: WasmPtr<__wasi_cidr_t, MemoryType>, naddrs: WasmPtr, ) -> __wasi_errno_t { @@ -710,21 +710,21 @@ pub(crate) fn port_addr_list( } pub(crate) fn port_mac( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ret_mac: WasmPtr<__wasi_hardwareaddress_t, MemoryType>, ) -> __wasi_errno_t { super::port_mac::(ctx, ret_mac) } pub(crate) fn port_gateway_set( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { super::port_gateway_set::(ctx, ip) } pub(crate) fn port_route_add( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, cidr: WasmPtr<__wasi_cidr_t, MemoryType>, via_router: WasmPtr<__wasi_addr_t, MemoryType>, preferred_until: WasmPtr<__wasi_option_timestamp_t, MemoryType>, @@ -734,18 +734,18 @@ pub(crate) fn port_route_add( } pub(crate) fn port_route_remove( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, ip: WasmPtr<__wasi_addr_t, MemoryType>, ) -> __wasi_errno_t { super::port_route_remove::(ctx, ip) } -pub(crate) fn port_route_clear(ctx: ContextMut<'_, WasiEnv>) -> __wasi_errno_t { +pub(crate) fn port_route_clear(ctx: FunctionEnvMut) -> __wasi_errno_t { super::port_route_clear(ctx) } pub(crate) fn port_route_list( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, routes: WasmPtr<__wasi_route_t, MemoryType>, nroutes: WasmPtr, ) -> __wasi_errno_t { @@ -753,7 +753,7 @@ pub(crate) fn port_route_list( } pub(crate) fn ws_connect( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, url: WasmPtr, url_len: MemoryOffset, ret_sock: WasmPtr<__wasi_fd_t, MemoryType>, @@ -762,7 +762,7 @@ pub(crate) fn ws_connect( } pub(crate) fn http_request( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, url: WasmPtr, url_len: MemoryOffset, method: WasmPtr, @@ -786,7 +786,7 @@ pub(crate) fn http_request( } pub(crate) fn http_status( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, status: WasmPtr<__wasi_http_status_t, MemoryType>, status_text: WasmPtr, @@ -798,7 +798,7 @@ pub(crate) fn http_status( } pub(crate) fn sock_status( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ret_status: WasmPtr<__wasi_sockstatus_t, MemoryType>, ) -> __wasi_errno_t { @@ -806,7 +806,7 @@ pub(crate) fn sock_status( } pub(crate) fn sock_addr_local( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ret_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -814,7 +814,7 @@ pub(crate) fn sock_addr_local( } pub(crate) fn sock_addr_peer( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ro_addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -822,7 +822,7 @@ pub(crate) fn sock_addr_peer( } pub(crate) fn sock_open( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, af: __wasi_addressfamily_t, ty: __wasi_socktype_t, pt: __wasi_sockproto_t, @@ -832,7 +832,7 @@ pub(crate) fn sock_open( } pub(crate) fn sock_set_opt_flag( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, flag: __wasi_bool_t, @@ -841,7 +841,7 @@ pub(crate) fn sock_set_opt_flag( } pub(crate) fn sock_get_opt_flag( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_flag: WasmPtr<__wasi_bool_t, MemoryType>, @@ -850,7 +850,7 @@ pub(crate) fn sock_get_opt_flag( } pub fn sock_set_opt_time( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, @@ -859,7 +859,7 @@ pub fn sock_set_opt_time( } pub fn sock_get_opt_time( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_time: WasmPtr<__wasi_option_timestamp_t, MemoryType>, @@ -868,7 +868,7 @@ pub fn sock_get_opt_time( } pub fn sock_set_opt_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, size: __wasi_filesize_t, @@ -877,7 +877,7 @@ pub fn sock_set_opt_size( } pub fn sock_get_opt_size( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, opt: __wasi_sockoption_t, ret_size: WasmPtr<__wasi_filesize_t, MemoryType>, @@ -886,7 +886,7 @@ pub fn sock_get_opt_size( } pub(crate) fn sock_join_multicast_v4( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, @@ -895,7 +895,7 @@ pub(crate) fn sock_join_multicast_v4( } pub(crate) fn sock_leave_multicast_v4( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip4_t, MemoryType>, iface: WasmPtr<__wasi_addr_ip4_t, MemoryType>, @@ -904,7 +904,7 @@ pub(crate) fn sock_leave_multicast_v4( } pub(crate) fn sock_join_multicast_v6( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, @@ -913,7 +913,7 @@ pub(crate) fn sock_join_multicast_v6( } pub(crate) fn sock_leave_multicast_v6( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, multiaddr: WasmPtr<__wasi_addr_ip6_t, MemoryType>, iface: u32, @@ -922,7 +922,7 @@ pub(crate) fn sock_leave_multicast_v6( } pub(crate) fn sock_bind( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -930,7 +930,7 @@ pub(crate) fn sock_bind( } pub(crate) fn sock_listen( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, backlog: MemoryOffset, ) -> __wasi_errno_t { @@ -938,7 +938,7 @@ pub(crate) fn sock_listen( } pub(crate) fn sock_accept( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, fd_flags: __wasi_fdflags_t, ro_fd: WasmPtr<__wasi_fd_t, MemoryType>, @@ -948,7 +948,7 @@ pub(crate) fn sock_accept( } pub(crate) fn sock_connect( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, addr: WasmPtr<__wasi_addr_port_t, MemoryType>, ) -> __wasi_errno_t { @@ -956,7 +956,7 @@ pub(crate) fn sock_connect( } pub(crate) fn sock_recv( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -976,7 +976,7 @@ pub(crate) fn sock_recv( } pub(crate) fn sock_recv_from( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, ri_data: WasmPtr<__wasi_iovec_t, MemoryType>, ri_data_len: MemoryOffset, @@ -998,7 +998,7 @@ pub(crate) fn sock_recv_from( } pub(crate) fn sock_send( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, @@ -1009,7 +1009,7 @@ pub(crate) fn sock_send( } pub(crate) fn sock_send_to( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, si_data: WasmPtr<__wasi_ciovec_t, MemoryType>, si_data_len: MemoryOffset, @@ -1029,7 +1029,7 @@ pub(crate) fn sock_send_to( } pub(crate) fn sock_send_file( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, out_fd: __wasi_fd_t, in_fd: __wasi_fd_t, offset: __wasi_filesize_t, @@ -1040,7 +1040,7 @@ pub(crate) fn sock_send_file( } pub(crate) fn sock_shutdown( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, sock: __wasi_fd_t, how: __wasi_sdflags_t, ) -> __wasi_errno_t { @@ -1048,7 +1048,7 @@ pub(crate) fn sock_shutdown( } pub(crate) fn resolve( - ctx: ContextMut<'_, WasiEnv>, + ctx: FunctionEnvMut, host: WasmPtr, host_len: MemoryOffset, port: u16, diff --git a/lib/wasi/tests/stdio.rs b/lib/wasi/tests/stdio.rs index 3af490b8d74..78b93520e1a 100644 --- a/lib/wasi/tests/stdio.rs +++ b/lib/wasi/tests/stdio.rs @@ -1,6 +1,6 @@ use std::io::{Read, Write}; -use wasmer::{AsContextMut, Context, Instance, Module, Store}; +use wasmer::{Instance, Module, Store}; use wasmer_wasi::{Pipe, WasiState}; mod sys { @@ -41,8 +41,8 @@ mod js { } fn test_stdout() { - let store = Store::default(); - let module = Module::new(&store, br#" + let mut store = Store::default(); + let module = Module::new(&mut store, br#" (module ;; Import the required fd_write WASI function which will write the given io vectors to stdout ;; The function signature for fd_write is: @@ -74,28 +74,23 @@ fn test_stdout() { // Create the `WasiEnv`. let mut stdout = Pipe::default(); - let mut wasi_env = WasiState::new("command-name") + let wasi_env = WasiState::new("command-name") .args(&["Gordon"]) .stdout(Box::new(stdout.clone())) - .finalize() + .finalize(&mut store) .unwrap(); - // Create a context state that will hold all objects created by this Instance - let mut ctx = Context::new(&store, wasi_env.clone()); - // Generate an `ImportObject`. - let import_object = wasi_env - .import_object(&mut ctx.as_context_mut(), &module) - .unwrap(); + let import_object = wasi_env.import_object(&mut store, &module).unwrap(); // Let's instantiate the module with the imports. - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - ctx.data_mut().set_memory(memory.clone()); + wasi_env.data_mut(&mut store).set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); - start.call(&mut ctx, &[]).unwrap(); + start.call(&mut store, &[]).unwrap(); let mut stdout_str = String::new(); stdout.read_to_string(&mut stdout_str).unwrap(); @@ -104,7 +99,7 @@ fn test_stdout() { } fn test_env() { - let store = Store::default(); + let mut store = Store::default(); let module = Module::new(&store, include_bytes!("envvar.wasm")).unwrap(); #[cfg(feature = "js")] @@ -123,27 +118,22 @@ fn test_env() { .env("TEST", "VALUE") .env("TEST2", "VALUE2"); // panic!("envs: {:?}", wasi_state_builder.envs); - let mut wasi_env = wasi_state_builder + let wasi_env = wasi_state_builder .stdout(Box::new(stdout.clone())) - .finalize() + .finalize(&mut store) .unwrap(); - // Create a context state that will hold all objects created by this Instance - let mut ctx = Context::new(&store, wasi_env.clone()); - // Generate an `ImportObject`. - let import_object = wasi_env - .import_object(&mut ctx.as_context_mut(), &module) - .unwrap(); + let import_object = wasi_env.import_object(&mut store, &module).unwrap(); // Let's instantiate the module with the imports. - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - ctx.data_mut().set_memory(memory.clone()); + wasi_env.data_mut(&mut store).set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); - start.call(&mut ctx, &[]).unwrap(); + start.call(&mut store, &[]).unwrap(); let mut stdout_str = String::new(); stdout.read_to_string(&mut stdout_str).unwrap(); @@ -152,36 +142,31 @@ fn test_env() { } fn test_stdin() { - let store = Store::default(); + let mut store = Store::default(); let module = Module::new(&store, include_bytes!("stdin-hello.wasm")).unwrap(); // Create the `WasiEnv`. let mut stdin = Pipe::new(); - let mut wasi_env = WasiState::new("command-name") + let wasi_env = WasiState::new("command-name") .stdin(Box::new(stdin.clone())) - .finalize() + .finalize(&mut store) .unwrap(); // Write to STDIN let buf = "Hello, stdin!\n".as_bytes().to_owned(); stdin.write(&buf[..]).unwrap(); - // Create a context state that will hold all objects created by this Instance - let mut ctx = Context::new(&store, wasi_env.clone()); - // Generate an `ImportObject`. - let import_object = wasi_env - .import_object(&mut ctx.as_context_mut(), &module) - .unwrap(); + let import_object = wasi_env.import_object(&mut store, &module).unwrap(); // Let's instantiate the module with the imports. - let instance = Instance::new(&mut ctx, &module, &import_object).unwrap(); + let instance = Instance::new(&mut store, &module, &import_object).unwrap(); let memory = instance.exports.get_memory("memory").unwrap(); - ctx.data_mut().set_memory(memory.clone()); + wasi_env.data_mut(&mut store).set_memory(memory.clone()); // Let's call the `_start` function, which is our `main` function in Rust. let start = instance.exports.get_function("_start").unwrap(); - let result = start.call(&mut ctx, &[]); + let result = start.call(&mut store, &[]); assert!(!result.is_err()); // We assure stdin is now empty diff --git a/tests/compilers/deterministic.rs b/tests/compilers/deterministic.rs index 9c9070ce5c0..83a9a0ef2cb 100644 --- a/tests/compilers/deterministic.rs +++ b/tests/compilers/deterministic.rs @@ -1,8 +1,8 @@ use anyhow::Result; -use wasmer::{wat2wasm, Module}; +use wasmer::{wat2wasm, Module, Store}; fn compile_and_compare(wasm: &[u8]) -> Result<()> { - let store = Default::default(); + let store = Store::default(); // compile for first time let module = Module::new(&store, wasm)?; diff --git a/tests/compilers/imports.rs b/tests/compilers/imports.rs index 232103d0a86..558e4fa51bd 100644 --- a/tests/compilers/imports.rs +++ b/tests/compilers/imports.rs @@ -8,7 +8,7 @@ use std::sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, Arc, }; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::Type as ValueType; use wasmer::*; @@ -47,28 +47,28 @@ fn get_module(store: &Store) -> Result { #[compiler_test(imports)] #[serial_test::serial(dynamic_function)] fn dynamic_function(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module(&store)?; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); static HITS: AtomicUsize = AtomicUsize::new(0); let imports = imports! { "host" => { - "0" => Function::new(&mut ctx, FunctionType::new(vec![], vec![]), |_ctx, _values| { + "0" => Function::new(&mut store, &env, FunctionType::new(vec![], vec![]), |_ctx, _values| { assert_eq!(HITS.fetch_add(1, SeqCst), 0); Ok(vec![]) }), - "1" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32], vec![ValueType::I32]), |_ctx, values| { + "1" => Function::new(&mut store, &env, FunctionType::new(vec![ValueType::I32], vec![ValueType::I32]), |_ctx, values| { assert_eq!(values[0], Value::I32(0)); assert_eq!(HITS.fetch_add(1, SeqCst), 1); Ok(vec![Value::I32(1)]) }), - "2" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32, ValueType::I64], vec![]), |_ctx, values| { + "2" => Function::new(&mut store, &env, FunctionType::new(vec![ValueType::I32, ValueType::I64], vec![]), |_ctx, values| { assert_eq!(values[0], Value::I32(2)); assert_eq!(values[1], Value::I64(3)); assert_eq!(HITS.fetch_add(1, SeqCst), 2); Ok(vec![]) }), - "3" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32, ValueType::I64, ValueType::I32, ValueType::F32, ValueType::F64], vec![]), |_ctx, values| { + "3" => Function::new(&mut store, &env, FunctionType::new(vec![ValueType::I32, ValueType::I64, ValueType::I32, ValueType::F32, ValueType::F64], vec![]), |_ctx, values| { assert_eq!(values[0], Value::I32(100)); assert_eq!(values[1], Value::I64(200)); assert_eq!(values[2], Value::I32(300)); @@ -79,14 +79,14 @@ fn dynamic_function(config: crate::Config) -> Result<()> { }), } }; - Instance::new(&mut ctx, &module, &imports)?; + Instance::new(&mut store, &module, &imports)?; assert_eq!(HITS.swap(0, SeqCst), 4); Ok(()) } #[compiler_test(imports)] fn dynamic_function_with_env(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module(&store)?; #[derive(Clone)] @@ -104,9 +104,10 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { let env: Env = Env { counter: Arc::new(AtomicUsize::new(0)), }; - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); let f0 = Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new(vec![], vec![]), |ctx, _values| { assert_eq!(ctx.data().fetch_add(1, SeqCst), 0); @@ -114,7 +115,8 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { }, ); let f1 = Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new(vec![ValueType::I32], vec![ValueType::I32]), |ctx, values| { assert_eq!(values[0], Value::I32(0)); @@ -123,7 +125,8 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { }, ); let f2 = Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new(vec![ValueType::I32, ValueType::I64], vec![]), |ctx, values| { assert_eq!(values[0], Value::I32(2)); @@ -133,7 +136,8 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { }, ); let f3 = Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new( vec![ ValueType::I32, @@ -155,7 +159,7 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { }, ); Instance::new( - &mut ctx, + &mut store, &module, &imports! { "host" => { @@ -166,34 +170,39 @@ fn dynamic_function_with_env(config: crate::Config) -> Result<()> { }, }, )?; - assert_eq!(ctx.data_mut().load(SeqCst), 4); + assert_eq!(env.as_mut(&mut store).load(SeqCst), 4); Ok(()) } #[compiler_test(imports)] #[serial_test::serial(static_function)] fn static_function(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module(&store)?; static HITS: AtomicUsize = AtomicUsize::new(0); - let mut ctx = WasmerContext::new(&store, ()); - let f0 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + let mut env = FunctionEnv::new(&mut store, ()); + let f0 = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<_>| { assert_eq!(HITS.fetch_add(1, SeqCst), 0); }); - let f1 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, x: i32| -> i32 { + let f1 = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<_>, x: i32| -> i32 { assert_eq!(x, 0); assert_eq!(HITS.fetch_add(1, SeqCst), 1); 1 }); - let f2 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, x: i32, y: i64| { - assert_eq!(x, 2); - assert_eq!(y, 3); - assert_eq!(HITS.fetch_add(1, SeqCst), 2); - }); + let f2 = Function::new_native( + &mut store, + &env, + |_ctx: FunctionEnvMut<_>, x: i32, y: i64| { + assert_eq!(x, 2); + assert_eq!(y, 3); + assert_eq!(HITS.fetch_add(1, SeqCst), 2); + }, + ); let f3 = Function::new_native( - &mut ctx, - |_ctx: ContextMut<_>, a: i32, b: i64, c: i32, d: f32, e: f64| { + &mut store, + &env, + |_ctx: FunctionEnvMut<_>, a: i32, b: i64, c: i32, d: f32, e: f64| { assert_eq!(a, 100); assert_eq!(b, 200); assert_eq!(c, 300); @@ -203,7 +212,7 @@ fn static_function(config: crate::Config) -> Result<()> { }, ); Instance::new( - &mut ctx, + &mut store, &module, &imports! { "host" => { @@ -221,30 +230,36 @@ fn static_function(config: crate::Config) -> Result<()> { #[compiler_test(imports)] #[serial_test::serial(static_function_with_results)] fn static_function_with_results(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module(&store)?; static HITS: AtomicUsize = AtomicUsize::new(0); - let mut ctx = WasmerContext::new(&store, ()); - let f0 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + let mut env = FunctionEnv::new(&mut store, ()); + let f0 = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<_>| { assert_eq!(HITS.fetch_add(1, SeqCst), 0); }); let f1 = Function::new_native( - &mut ctx, - |_ctx: ContextMut<_>, x: i32| -> Result { + &mut store, + &env, + |_ctx: FunctionEnvMut<_>, x: i32| -> Result { assert_eq!(x, 0); assert_eq!(HITS.fetch_add(1, SeqCst), 1); Ok(1) }, ); - let f2 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>, x: i32, y: i64| { - assert_eq!(x, 2); - assert_eq!(y, 3); - assert_eq!(HITS.fetch_add(1, SeqCst), 2); - }); + let f2 = Function::new_native( + &mut store, + &env, + |_ctx: FunctionEnvMut<_>, x: i32, y: i64| { + assert_eq!(x, 2); + assert_eq!(y, 3); + assert_eq!(HITS.fetch_add(1, SeqCst), 2); + }, + ); let f3 = Function::new_native( - &mut ctx, - |_ctx: ContextMut<_>, a: i32, b: i64, c: i32, d: f32, e: f64| { + &mut store, + &env, + |_ctx: FunctionEnvMut<_>, a: i32, b: i64, c: i32, d: f32, e: f64| { assert_eq!(a, 100); assert_eq!(b, 200); assert_eq!(c, 300); @@ -254,7 +269,7 @@ fn static_function_with_results(config: crate::Config) -> Result<()> { }, ); Instance::new( - &mut ctx, + &mut store, &module, &imports! { "host" => { @@ -271,7 +286,7 @@ fn static_function_with_results(config: crate::Config) -> Result<()> { #[compiler_test(imports)] fn static_function_with_env(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module(&store)?; #[derive(Clone)] @@ -285,23 +300,32 @@ fn static_function_with_env(config: crate::Config) -> Result<()> { } let env: Env = Env(Arc::new(AtomicUsize::new(0))); - let mut ctx = WasmerContext::new(&store, env); - let f0 = Function::new_native(&mut ctx, |ctx: ContextMut| { + let mut env = FunctionEnv::new(&mut store, env); + let f0 = Function::new_native(&mut store, &env, |ctx: FunctionEnvMut| { assert_eq!(ctx.data().fetch_add(1, SeqCst), 0); }); - let f1 = Function::new_native(&mut ctx, |ctx: ContextMut, x: i32| -> i32 { - assert_eq!(x, 0); - assert_eq!(ctx.data().fetch_add(1, SeqCst), 1); - 1 - }); - let f2 = Function::new_native(&mut ctx, |ctx: ContextMut, x: i32, y: i64| { - assert_eq!(x, 2); - assert_eq!(y, 3); - assert_eq!(ctx.data().fetch_add(1, SeqCst), 2); - }); + let f1 = Function::new_native( + &mut store, + &env, + |ctx: FunctionEnvMut, x: i32| -> i32 { + assert_eq!(x, 0); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 1); + 1 + }, + ); + let f2 = Function::new_native( + &mut store, + &env, + |ctx: FunctionEnvMut, x: i32, y: i64| { + assert_eq!(x, 2); + assert_eq!(y, 3); + assert_eq!(ctx.data().fetch_add(1, SeqCst), 2); + }, + ); let f3 = Function::new_native( - &mut ctx, - |ctx: ContextMut, a: i32, b: i64, c: i32, d: f32, e: f64| { + &mut store, + &env, + |ctx: FunctionEnvMut, a: i32, b: i64, c: i32, d: f32, e: f64| { assert_eq!(a, 100); assert_eq!(b, 200); assert_eq!(c, 300); @@ -311,7 +335,7 @@ fn static_function_with_env(config: crate::Config) -> Result<()> { }, ); Instance::new( - &mut ctx, + &mut store, &module, &imports! { "host" => { @@ -322,13 +346,13 @@ fn static_function_with_env(config: crate::Config) -> Result<()> { }, }, )?; - assert_eq!(ctx.data_mut().load(SeqCst), 4); + assert_eq!(env.as_mut(&mut store).load(SeqCst), 4); Ok(()) } #[compiler_test(imports)] fn static_function_that_fails(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (import "host" "0" (func)) @@ -339,15 +363,16 @@ fn static_function_that_fails(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &wat)?; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let f0 = Function::new_native( - &mut ctx, - |_ctx: ContextMut<_>| -> Result { + &mut store, + &env, + |_ctx: FunctionEnvMut<_>| -> Result { Err(RuntimeError::new("oops")) }, ); let result = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "host" => { @@ -384,7 +409,7 @@ fn get_module2(store: &Store) -> Result { #[compiler_test(imports)] fn dynamic_function_with_env_wasmer_env_init_works(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module2(&store)?; #[allow(dead_code)] @@ -394,9 +419,10 @@ fn dynamic_function_with_env_wasmer_env_init_works(config: crate::Config) -> Res } let env: Env = Env { memory: None }; - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); let f0 = Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new(vec![], vec![]), |ctx, _values| { assert!(ctx.data().memory.as_ref().is_some()); @@ -404,7 +430,7 @@ fn dynamic_function_with_env_wasmer_env_init_works(config: crate::Config) -> Res }, ); let instance = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "host" => { @@ -413,15 +439,15 @@ fn dynamic_function_with_env_wasmer_env_init_works(config: crate::Config) -> Res }, )?; let memory = instance.exports.get_memory("memory")?; - ctx.data_mut().memory = Some(memory.clone()); - let f: TypedFunction<(), ()> = instance.exports.get_typed_function(&ctx, "main")?; - f.call(&mut ctx)?; + env.as_mut(&mut store).memory = Some(memory.clone()); + let f: TypedFunction<(), ()> = instance.exports.get_typed_function(&mut store, "main")?; + f.call(&mut store)?; Ok(()) } #[compiler_test(imports)] fn multi_use_host_fn_manages_memory_correctly(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module2(&store)?; #[allow(dead_code)] @@ -439,30 +465,30 @@ fn multi_use_host_fn_manages_memory_correctly(config: crate::Config) -> Result<( }*/ let env: Env = Env { memory: None }; - let mut ctx = WasmerContext::new(&store, env); - fn host_fn(ctx: ContextMut) { + let mut env = FunctionEnv::new(&mut store, env); + fn host_fn(ctx: FunctionEnvMut) { assert!(ctx.data().memory.is_some()); println!("Hello, world!"); } let imports = imports! { "host" => { - "fn" => Function::new_native(&mut ctx, host_fn), + "fn" => Function::new_native(&mut store, &env, host_fn), }, }; - let instance1 = Instance::new(&mut ctx, &module, &imports)?; - let instance2 = Instance::new(&mut ctx, &module, &imports)?; + let instance1 = Instance::new(&mut store, &module, &imports)?; + let instance2 = Instance::new(&mut store, &module, &imports)?; { - let f1: TypedFunction<(), ()> = instance1.exports.get_typed_function(&mut ctx, "main")?; + let f1: TypedFunction<(), ()> = instance1.exports.get_typed_function(&mut store, "main")?; let memory = instance1.exports.get_memory("memory")?; - ctx.data_mut().memory = Some(memory.clone()); - f1.call(&mut ctx)?; + env.as_mut(&mut store).memory = Some(memory.clone()); + f1.call(&mut store)?; } drop(instance1); { - let f2: TypedFunction<(), ()> = instance2.exports.get_typed_function(&mut ctx, "main")?; + let f2: TypedFunction<(), ()> = instance2.exports.get_typed_function(&mut store, "main")?; let memory = instance2.exports.get_memory("memory")?; - ctx.data_mut().memory = Some(memory.clone()); - f2.call(&mut ctx)?; + env.as_mut(&mut store).memory = Some(memory.clone()); + f2.call(&mut store)?; } drop(instance2); Ok(()) @@ -470,15 +496,15 @@ fn multi_use_host_fn_manages_memory_correctly(config: crate::Config) -> Result<( #[compiler_test(imports)] fn instance_local_memory_lifetime(config: crate::Config) -> Result<()> { - let store = config.store(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = config.store(); + let mut env = FunctionEnv::new(&mut store, ()); let memory: Memory = { let wat = r#"(module (memory $mem 1) (export "memory" (memory $mem)) )"#; let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let instance = Instance::new(&mut store, &module, &imports! {})?; instance.exports.get_memory("memory")?.clone() }; @@ -499,13 +525,13 @@ fn instance_local_memory_lifetime(config: crate::Config) -> Result<()> { "memory" => memory, }, }; - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; let set_at: TypedFunction<(i32, i32), ()> = - instance.exports.get_typed_function(&mut ctx, "set_at")?; + instance.exports.get_typed_function(&mut store, "set_at")?; let get_at: TypedFunction = - instance.exports.get_typed_function(&mut ctx, "get_at")?; - set_at.call(&mut ctx, 200, 123)?; - assert_eq!(get_at.call(&mut ctx, 200)?, 123); + instance.exports.get_typed_function(&mut store, "get_at")?; + set_at.call(&mut store, 200, 123)?; + assert_eq!(get_at.call(&mut store, 200)?, 123); Ok(()) } diff --git a/tests/compilers/issues.rs b/tests/compilers/issues.rs index 07064cc95ca..03a301e8690 100644 --- a/tests/compilers/issues.rs +++ b/tests/compilers/issues.rs @@ -1,6 +1,6 @@ //! This file is mainly to assure specific issues are working well use anyhow::Result; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::*; /// Corruption of WasmerEnv when using call indirect. @@ -11,7 +11,7 @@ use wasmer::*; /// https://github.com/wasmerio/wasmer/issues/2329 #[compiler_test(issues)] fn issue_2329(mut config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); #[derive(Clone, Default)] pub struct Env { @@ -24,8 +24,8 @@ fn issue_2329(mut config: crate::Config) -> Result<()> { } } - pub fn read_memory(ctx: ContextMut, guest_ptr: u32) -> u32 { - dbg!(ctx.data().memory.as_ref()); + pub fn read_memory(mut ctx: FunctionEnvMut, guest_ptr: u32) -> u32 { + dbg!(ctx.data_mut().memory.as_ref()); dbg!(guest_ptr); 0 } @@ -61,26 +61,27 @@ fn issue_2329(mut config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; let env = Env::new(); - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); let imports: Imports = imports! { "env" => { "__read_memory" => Function::new_native( - &mut ctx, + &mut store, + &env, read_memory ), } }; - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; instance .exports .get_function("read_memory")? - .call(&mut ctx, &[])?; + .call(&mut store, &[])?; Ok(()) } #[compiler_test(issues)] fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); #[derive(Clone)] pub struct Env { @@ -88,7 +89,7 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { } pub fn banana( - mut ctx: ContextMut, + mut ctx: FunctionEnvMut, a: u64, b: u64, c: u64, @@ -100,24 +101,24 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { ) -> u64 { println!("{:?}", (a, b, c, d, e, f, g, h)); let mut buf = vec![0; d as usize]; - let memory = ctx.data().memory.as_ref().unwrap(); - memory.read(&ctx, e, &mut buf).unwrap(); + let memory = ctx.data_mut().memory.as_ref().unwrap().clone(); + memory.read(&mut ctx, e, &mut buf).unwrap(); let input_string = std::str::from_utf8(&buf).unwrap(); assert_eq!(input_string, "bananapeach"); 0 } - pub fn mango(ctx: ContextMut, a: u64) {} + pub fn mango(ctx: FunctionEnvMut, a: u64) {} - pub fn chaenomeles(ctx: ContextMut, a: u64) -> u64 { + pub fn chaenomeles(ctx: FunctionEnvMut, a: u64) -> u64 { 0 } - pub fn peach(ctx: ContextMut, a: u64, b: u64) -> u64 { + pub fn peach(ctx: FunctionEnvMut, a: u64, b: u64) -> u64 { 0 } - pub fn gas(ctx: ContextMut, a: u32) {} + pub fn gas(ctx: FunctionEnvMut, a: u32) {} let wat = r#" (module @@ -187,27 +188,30 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { let module = Module::new(&store, wat)?; let env = Env { memory: None }; - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); let memory = Memory::new( - &mut ctx, + &mut store, MemoryType::new(Pages(1024), Some(Pages(2048)), false), ) .unwrap(); - ctx.data_mut().memory = Some(memory.clone()); + env.as_mut(&mut store).memory = Some(memory.clone()); let mut exports = Exports::new(); exports.insert("memory", memory); - exports.insert("banana", Function::new_native(&mut ctx, banana)); - exports.insert("peach", Function::new_native(&mut ctx, peach)); - exports.insert("chaenomeles", Function::new_native(&mut ctx, chaenomeles)); - exports.insert("mango", Function::new_native(&mut ctx, mango)); - exports.insert("gas", Function::new_native(&mut ctx, gas)); + exports.insert("banana", Function::new_native(&mut store, &env, banana)); + exports.insert("peach", Function::new_native(&mut store, &env, peach)); + exports.insert( + "chaenomeles", + Function::new_native(&mut store, &env, chaenomeles), + ); + exports.insert("mango", Function::new_native(&mut store, &env, mango)); + exports.insert("gas", Function::new_native(&mut store, &env, gas)); let mut imports = Imports::new(); imports.register_namespace("env", exports); - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; instance .exports .get_function("repro")? - .call(&mut ctx, &[])?; + .call(&mut store, &[])?; Ok(()) } @@ -217,7 +221,7 @@ fn call_with_static_data_pointers(mut config: crate::Config) -> Result<()> { /// available compilers. #[compiler_test(issues)] fn regression_gpr_exhaustion_for_calls(mut config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module (type (;0;) (func (param f64) (result i32))) @@ -244,9 +248,9 @@ fn regression_gpr_exhaustion_for_calls(mut config: crate::Config) -> Result<()> i32.const 0) (table (;0;) 1 1 funcref)) "#; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let module = Module::new(&store, wat)?; let imports: Imports = imports! {}; - let instance = Instance::new(&mut ctx, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports)?; Ok(()) } diff --git a/tests/compilers/metering.rs b/tests/compilers/metering.rs index faf43e3ee55..4df524aad4b 100644 --- a/tests/compilers/metering.rs +++ b/tests/compilers/metering.rs @@ -3,7 +3,7 @@ use wasmer_middlewares::Metering; use std::sync::Arc; use wasmer::wasmparser::Operator; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::*; fn cost_always_one(_: &Operator) -> u64 { @@ -14,21 +14,22 @@ fn run_add_with_limit(mut config: crate::Config, limit: u64) -> Result<()> { config .middlewares .push(Arc::new(Metering::new(limit, cost_always_one))); - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func (export "add") (param i32 i32) (result i32) (i32.add (local.get 0) (local.get 1))) )"#; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! {}; let module = Module::new(&store, wat).unwrap(); - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; - f.call(&mut ctx, 4, 6)?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut store, "add")?; + f.call(&mut store, 4, 6)?; Ok(()) } @@ -36,7 +37,7 @@ fn run_loop(mut config: crate::Config, limit: u64, iter_count: i32) -> Result<() config .middlewares .push(Arc::new(Metering::new(limit, cost_always_one))); - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func (export "test") (param i32) (local i32) @@ -53,14 +54,14 @@ fn run_loop(mut config: crate::Config, limit: u64, iter_count: i32) -> Result<() ) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; - let f: TypedFunction = instance.exports.get_typed_function(&mut ctx, "test")?; - f.call(&mut ctx, iter_count)?; + let f: TypedFunction = instance.exports.get_typed_function(&mut store, "test")?; + f.call(&mut store, iter_count)?; Ok(()) } @@ -154,20 +155,20 @@ fn complex_loop(mut config: crate::Config) -> Result<()> { config .middlewares .push(Arc::new(Metering::new(100, cost_always_one))); - let store = config.store(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = config.store(); + let mut env = FunctionEnv::new(&mut store, ()); let module = Module::new(&store, WAT).unwrap(); let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; let f: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function(&mut ctx, "add_to")?; + instance.exports.get_typed_function(&mut store, "add_to")?; // FIXME: Since now a metering error is signaled with an `unreachable`, it is impossible to verify // the error type. Fix this later. - f.call(&mut ctx, 10_000_000, 4).unwrap_err(); + f.call(&mut store, 10_000_000, 4).unwrap_err(); Ok(()) } diff --git a/tests/compilers/middlewares.rs b/tests/compilers/middlewares.rs index 700051da7b7..b7687ba4bf2 100644 --- a/tests/compilers/middlewares.rs +++ b/tests/compilers/middlewares.rs @@ -2,7 +2,7 @@ use anyhow::Result; use std::sync::Arc; use wasmer::wasmparser::Operator; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::*; #[derive(Debug)] @@ -93,21 +93,22 @@ fn middleware_basic(mut config: crate::Config) -> Result<()> { config.set_middlewares(vec![ Arc::new(Add2MulGen { value_off: 0 }) as Arc ]); - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func (export "add") (param i32 i32) (result i32) (i32.add (local.get 0) (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; - let result = f.call(&mut ctx, 4, 6)?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut store, "add")?; + let result = f.call(&mut store, 4, 6)?; assert_eq!(result, 24); Ok(()) } @@ -117,20 +118,21 @@ fn middleware_one_to_multi(mut config: crate::Config) -> Result<()> { config.set_middlewares(vec![ Arc::new(Add2MulGen { value_off: 1 }) as Arc ]); - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func (export "add") (param i32 i32) (result i32) (i32.add (local.get 0) (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; - let result = f.call(&mut ctx, 4, 6)?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut store, "add")?; + let result = f.call(&mut store, 4, 6)?; assert_eq!(result, 25); Ok(()) } @@ -138,7 +140,7 @@ fn middleware_one_to_multi(mut config: crate::Config) -> Result<()> { #[compiler_test(middlewares)] fn middleware_multi_to_one(mut config: crate::Config) -> Result<()> { config.set_middlewares(vec![Arc::new(FusionGen) as Arc]); - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func (export "testfunc") (param i32 i32) (result i32) (local.get 0) @@ -148,14 +150,15 @@ fn middleware_multi_to_one(mut config: crate::Config) -> Result<()> { (i32.mul)) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function(&mut ctx, "testfunc")?; - let result = f.call(&mut ctx, 10, 20)?; + let f: TypedFunction<(i32, i32), i32> = instance + .exports + .get_typed_function(&mut store, "testfunc")?; + let result = f.call(&mut store, 10, 20)?; assert_eq!(result, 10); Ok(()) } @@ -166,20 +169,20 @@ fn middleware_chain_order_1(mut config: crate::Config) -> Result<()> { Arc::new(Add2MulGen { value_off: 0 }) as Arc, Arc::new(Add2MulGen { value_off: 2 }) as Arc, ]); - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func (export "add") (param i32 i32) (result i32) (i32.add (local.get 0) (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; - let result = f.call(&mut ctx, 4, 6)?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut store, "add")?; + let result = f.call(&mut store, 4, 6)?; assert_eq!(result, 24); Ok(()) } @@ -190,20 +193,20 @@ fn middleware_chain_order_2(mut config: crate::Config) -> Result<()> { Arc::new(Add2MulGen { value_off: 2 }) as Arc, Arc::new(Add2MulGen { value_off: 0 }) as Arc, ]); - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func (export "add") (param i32 i32) (result i32) (i32.add (local.get 0) (local.get 1))) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); let import_object = imports! {}; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; - let f: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut ctx, "add")?; - let result = f.call(&mut ctx, 4, 6)?; + let f: TypedFunction<(i32, i32), i32> = + instance.exports.get_typed_function(&mut store, "add")?; + let result = f.call(&mut store, 4, 6)?; assert_eq!(result, 48); Ok(()) } diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs index d260bc0635d..26f291938b3 100644 --- a/tests/compilers/multi_value_imports.rs +++ b/tests/compilers/multi_value_imports.rs @@ -37,7 +37,7 @@ macro_rules! mvr_test { #[compiler_test(multi_value_imports)] fn native(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module(&store)?; let instance = wasmer::Instance::new( &module, @@ -62,7 +62,7 @@ macro_rules! mvr_test { #[compiler_test(multi_value_imports)] fn dynamic(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); + let mut store = config.store(); let module = get_module(&store)?; let callback_fn = wasmer::Function::new(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn); let instance = wasmer::Instance::new( diff --git a/tests/compilers/native_functions.rs b/tests/compilers/native_functions.rs index fc756576a26..3f6ecac790c 100644 --- a/tests/compilers/native_functions.rs +++ b/tests/compilers/native_functions.rs @@ -2,12 +2,12 @@ use anyhow::Result; use std::convert::Infallible; use std::sync::{Arc, Mutex}; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::Type as ValueType; use wasmer::*; fn long_f( - _ctx: ContextMut<()>, + _ctx: FunctionEnvMut<()>, a: u32, b: u32, c: u32, @@ -31,7 +31,7 @@ fn long_f( + a as u64 * 1000000000 } -fn long_f_dynamic(_ctx: ContextMut<()>, values: &[Value]) -> Result, RuntimeError> { +fn long_f_dynamic(_ctx: FunctionEnvMut<()>, values: &[Value]) -> Result, RuntimeError> { Ok(vec![Value::I64( values[9].unwrap_i32() as i64 + values[8].unwrap_i32() as i64 * 10 @@ -48,7 +48,7 @@ fn long_f_dynamic(_ctx: ContextMut<()>, values: &[Value]) -> Result, #[compiler_test(native_functions)] fn native_function_works_for_wasm(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func $multiply (import "env" "multiply") (param i32 i32) (result i32)) (func (export "add") (param i32 i32) (result i32) @@ -59,32 +59,32 @@ fn native_function_works_for_wasm(config: crate::Config) -> anyhow::Result<()> { (call $multiply (local.get 1) (i32.const 2)))) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! { "env" => { - "multiply" => Function::new_native(&mut ctx, |_ctx: ContextMut<_>, a: i32, b: i32| a * b), + "multiply" => Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<_>, a: i32, b: i32| a * b), }, }; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; { let f: TypedFunction<(i32, i32), i32> = - instance.exports.get_typed_function(&mut ctx, "add")?; - let result = f.call(&mut ctx, 4, 6)?; + instance.exports.get_typed_function(&mut store, "add")?; + let result = f.call(&mut store, 4, 6)?; assert_eq!(result, 10); } { let f: &Function = instance.exports.get("double_then_add")?; - let result = f.call(&mut ctx, &[Value::I32(4), Value::I32(6)])?; + let result = f.call(&mut store, &[Value::I32(4), Value::I32(6)])?; assert_eq!(result[0], Value::I32(20)); } { let dyn_f: &Function = instance.exports.get("double_then_add")?; - let f: TypedFunction<(i32, i32), i32> = dyn_f.native(&mut ctx).unwrap(); - let result = f.call(&mut ctx, 4, 6)?; + let f: TypedFunction<(i32, i32), i32> = dyn_f.native(&mut store).unwrap(); + let result = f.call(&mut store, 4, 6)?; assert_eq!(result, 20); } @@ -93,28 +93,32 @@ fn native_function_works_for_wasm(config: crate::Config) -> anyhow::Result<()> { #[compiler_test(native_functions)] fn native_host_function_closure_panics(config: crate::Config) { - let store = config.store(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = config.store(); + let mut env = FunctionEnv::new(&mut store, ()); let state = 3; - Function::new_native(&mut ctx, move |_ctx: ContextMut<_>, _: i32| { + Function::new_native(&mut store, &env, move |_ctx: FunctionEnvMut<_>, _: i32| { println!("{}", state); }); } #[compiler_test(native_functions)] fn native_with_env_host_function_closure_panics(config: crate::Config) { - let store = config.store(); + let mut store = config.store(); let env: i32 = 4; - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); let state = 3; - Function::new_native(&mut ctx, move |_ctx: ContextMut, _: i32| { - println!("{}", state); - }); + Function::new_native( + &mut store, + &env, + move |_ctx: FunctionEnvMut, _: i32| { + println!("{}", state); + }, + ); } #[compiler_test(native_functions)] fn non_native_functions_and_closures_with_no_env_work(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func $multiply1 (import "env" "multiply1") (param i32 i32) (result i32)) (func $multiply2 (import "env" "multiply2") (param i32 i32) (result i32)) @@ -134,38 +138,38 @@ fn non_native_functions_and_closures_with_no_env_work(config: crate::Config) -> )"#; let module = Module::new(&store, wat).unwrap(); let env: i32 = 10; - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); let ty = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]); let captured_by_closure = 20; let import_object = imports! { "env" => { - "multiply1" => Function::new(&mut ctx, &ty, move |_ctx, args| { + "multiply1" => Function::new(&mut store, &env, &ty, move |_ctx, args| { if let (Value::I32(v1), Value::I32(v2)) = (&args[0], &args[1]) { Ok(vec![Value::I32(v1 * v2 * captured_by_closure)]) } else { panic!("Invalid arguments"); } }), - "multiply2" => Function::new(&mut ctx, &ty, move |ctx, args| { + "multiply2" => Function::new(&mut store, &env, &ty, move |ctx, args| { if let (Value::I32(v1), Value::I32(v2)) = (&args[0], &args[1]) { Ok(vec![Value::I32(v1 * v2 * captured_by_closure * ctx.data())]) } else { panic!("Invalid arguments"); } }), - "multiply3" => Function::new_native(&mut ctx, |_ctx: ContextMut<_>, arg1: i32, arg2: i32| -> i32 + "multiply3" => Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<_>, arg1: i32, arg2: i32| -> i32 {arg1 * arg2 }), - "multiply4" => Function::new_native(&mut ctx, |ctx: ContextMut, arg1: i32, arg2: i32| -> i32 + "multiply4" => Function::new_native(&mut store, &env, |ctx: FunctionEnvMut, arg1: i32, arg2: i32| -> i32 {arg1 * arg2 * ctx.data() }), }, }; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; let test: TypedFunction<(i32, i32, i32, i32, i32), i32> = - instance.exports.get_typed_function(&mut ctx, "test")?; + instance.exports.get_typed_function(&mut store, "test")?; - let result = test.call(&mut ctx, 2, 3, 4, 5, 6)?; + let result = test.call(&mut store, 2, 3, 4, 5, 6)?; let manually_computed_result = 6 * (5 * (4 * (3 * 2 * 20) * 10 * 20)) * 10; assert_eq!(result, manually_computed_result); Ok(()) @@ -173,7 +177,7 @@ fn non_native_functions_and_closures_with_no_env_work(config: crate::Config) -> #[compiler_test(native_functions)] fn native_function_works_for_wasm_function_manyparams(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#"(module (func $longf (import "env" "longf") (param i32 i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i64)) (func (export "longf_pure") (param i32 i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i64) @@ -182,27 +186,27 @@ fn native_function_works_for_wasm_function_manyparams(config: crate::Config) -> (call $longf (i32.const 1) (i32.const 2) (i32.const 3) (i32.const 4) (i32.const 5) (i32.const 6) (i64.const 7) (i64.const 8) (i32.const 9) (i32.const 0))) )"#; let module = Module::new(&store, wat).unwrap(); - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let import_object = imports! { "env" => { - "longf" => Function::new_native(&mut ctx, long_f), + "longf" => Function::new_native(&mut store, &env, long_f), }, }; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; { let dyn_f: &Function = instance.exports.get("longf")?; - let f: TypedFunction<(), i64> = dyn_f.native(&mut ctx).unwrap(); - let result = f.call(&mut ctx)?; + let f: TypedFunction<(), i64> = dyn_f.native(&mut store).unwrap(); + let result = f.call(&mut store)?; assert_eq!(result, 1234567890); } { let dyn_f: &Function = instance.exports.get("longf_pure")?; let f: TypedFunction<(u32, u32, u32, u32, u32, u16, u64, u64, u16, u32), i64> = - dyn_f.native(&mut ctx).unwrap(); - let result = f.call(&mut ctx, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; + dyn_f.native(&mut store).unwrap(); + let result = f.call(&mut store, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; assert_eq!(result, 1234567890); } @@ -213,8 +217,8 @@ fn native_function_works_for_wasm_function_manyparams(config: crate::Config) -> fn native_function_works_for_wasm_function_manyparams_dynamic( config: crate::Config, ) -> anyhow::Result<()> { - let store = config.store(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = config.store(); + let mut env = FunctionEnv::new(&mut store, ()); let wat = r#"(module (func $longf (import "env" "longf") (param i32 i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i64)) (func (export "longf_pure") (param i32 i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i64) @@ -226,24 +230,24 @@ fn native_function_works_for_wasm_function_manyparams_dynamic( let import_object = imports! { "env" => { - "longf" => Function::new(&mut ctx, FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I64 , ValueType::I64 ,ValueType::I32, ValueType::I32], vec![ValueType::I64]), long_f_dynamic), + "longf" => Function::new(&mut store, &env, FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I64 , ValueType::I64 ,ValueType::I32, ValueType::I32], vec![ValueType::I64]), long_f_dynamic), }, }; - let instance = Instance::new(&mut ctx, &module, &import_object)?; + let instance = Instance::new(&mut store, &module, &import_object)?; { let dyn_f: &Function = instance.exports.get("longf")?; - let f: TypedFunction<(), i64> = dyn_f.native(&mut ctx).unwrap(); - let result = f.call(&mut ctx)?; + let f: TypedFunction<(), i64> = dyn_f.native(&mut store).unwrap(); + let result = f.call(&mut store)?; assert_eq!(result, 1234567890); } { let dyn_f: &Function = instance.exports.get("longf_pure")?; let f: TypedFunction<(u32, u32, u32, u32, u32, u16, u64, u64, u16, u32), i64> = - dyn_f.native(&mut ctx).unwrap(); - let result = f.call(&mut ctx, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; + dyn_f.native(&mut store).unwrap(); + let result = f.call(&mut store, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; assert_eq!(result, 1234567890); } @@ -252,15 +256,15 @@ fn native_function_works_for_wasm_function_manyparams_dynamic( #[compiler_test(native_functions)] fn static_host_function_without_env(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = config.store(); + let mut env = FunctionEnv::new(&mut store, ()); - fn f(_ctx: ContextMut<()>, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { + fn f(_ctx: FunctionEnvMut<()>, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { (d * 4.0, c * 3.0, b * 2, a * 1) } fn f_ok( - _ctx: ContextMut<()>, + _ctx: FunctionEnvMut<()>, a: i32, b: i64, c: f32, @@ -270,7 +274,7 @@ fn static_host_function_without_env(config: crate::Config) -> anyhow::Result<()> } fn long_f( - _ctx: ContextMut<()>, + _ctx: FunctionEnvMut<()>, a: u32, b: u32, c: u32, @@ -291,30 +295,30 @@ fn static_host_function_without_env(config: crate::Config) -> anyhow::Result<()> // Native static host function that returns a tuple. { - let f = Function::new_native(&mut ctx, f); + let f = Function::new_native(&mut store, &env, f); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native(&mut ctx).unwrap(); - let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; + f.native(&mut store).unwrap(); + let result = f_native.call(&mut store, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); } // Native static host function that returns a tuple. { - let long_f = Function::new_native(&mut ctx, long_f); + let long_f = Function::new_native(&mut store, &env, long_f); let long_f_native: TypedFunction< (u32, u32, u32, u32, u32, u16, u64, u64, u16, u32), (u32, u64, u32), - > = long_f.native(&mut ctx).unwrap(); - let result = long_f_native.call(&mut ctx, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; + > = long_f.native(&mut store).unwrap(); + let result = long_f_native.call(&mut store, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0)?; assert_eq!(result, (654321, 87, 09)); } // Native static host function that returns a result of a tuple. { - let f = Function::new_native(&mut ctx, f_ok); + let f = Function::new_native(&mut store, &env, f_ok); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native(&mut ctx).unwrap(); - let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; + f.native(&mut store).unwrap(); + let result = f_native.call(&mut store, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); } @@ -323,9 +327,9 @@ fn static_host_function_without_env(config: crate::Config) -> anyhow::Result<()> #[compiler_test(native_functions)] fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); + let mut store = config.store(); - fn f(mut ctx: ContextMut, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { + fn f(mut ctx: FunctionEnvMut, a: i32, b: i64, c: f32, d: f64) -> (f64, f32, i64, i32) { let mut guard = ctx.data_mut().0.lock().unwrap(); assert_eq!(*guard, 100); *guard = 101; @@ -334,7 +338,7 @@ fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { } fn f_ok( - mut ctx: ContextMut, + mut ctx: FunctionEnvMut, a: i32, b: i64, c: f32, @@ -360,35 +364,35 @@ fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { // Native static host function that returns a tuple. { let env = Env(Arc::new(Mutex::new(100))); - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); - let f = Function::new_native(&mut ctx, f); + let f = Function::new_native(&mut store, &env, f); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native(&mut ctx).unwrap(); + f.native(&mut store).unwrap(); - assert_eq!(*ctx.data_mut().0.lock().unwrap(), 100); + assert_eq!(*env.as_mut(&mut store).0.lock().unwrap(), 100); - let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; + let result = f_native.call(&mut store, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); - assert_eq!(*ctx.data_mut().0.lock().unwrap(), 101); + assert_eq!(*env.as_mut(&mut store).0.lock().unwrap(), 101); } // Native static host function that returns a result of a tuple. { let env = Env(Arc::new(Mutex::new(100))); - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); - let f = Function::new_native(&mut ctx, f_ok); + let f = Function::new_native(&mut store, &env, f_ok); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native(&mut ctx).unwrap(); + f.native(&mut store).unwrap(); - assert_eq!(*ctx.data_mut().0.lock().unwrap(), 100); + assert_eq!(*env.as_mut(&mut store).0.lock().unwrap(), 100); - let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; + let result = f_native.call(&mut store, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); - assert_eq!(*ctx.data_mut().0.lock().unwrap(), 101); + assert_eq!(*env.as_mut(&mut store).0.lock().unwrap(), 101); } Ok(()) @@ -396,10 +400,11 @@ fn static_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { #[compiler_test(native_functions)] fn dynamic_host_function_without_env(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); - let mut ctx = WasmerContext::new(&store, ()); + let mut store = config.store(); + let mut env = FunctionEnv::new(&mut store, ()); let f = Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new( vec![ ValueType::I32, @@ -414,7 +419,7 @@ fn dynamic_host_function_without_env(config: crate::Config) -> anyhow::Result<() ValueType::I32, ], ), - |_ctx: ContextMut<_>, values| { + |_ctx: FunctionEnvMut<_>, values| { Ok(vec![ Value::F64(values[3].unwrap_f64() * 4.0), Value::F32(values[2].unwrap_f32() * 3.0), @@ -424,8 +429,8 @@ fn dynamic_host_function_without_env(config: crate::Config) -> anyhow::Result<() }, ); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native(&mut ctx).unwrap(); - let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; + f.native(&mut store).unwrap(); + let result = f_native.call(&mut store, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); @@ -434,7 +439,7 @@ fn dynamic_host_function_without_env(config: crate::Config) -> anyhow::Result<() #[compiler_test(native_functions)] fn dynamic_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { - let store = config.store(); + let mut store = config.store(); #[derive(Clone)] struct Env(Arc>); @@ -447,9 +452,10 @@ fn dynamic_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { } let env = Env(Arc::new(Mutex::new(100))); - let mut ctx = WasmerContext::new(&store, env); + let mut env = FunctionEnv::new(&mut store, env); let f = Function::new( - &mut ctx, + &mut store, + &env, FunctionType::new( vec![ ValueType::I32, @@ -480,14 +486,14 @@ fn dynamic_host_function_with_env(config: crate::Config) -> anyhow::Result<()> { ); let f_native: TypedFunction<(i32, i64, f32, f64), (f64, f32, i64, i32)> = - f.native(&mut ctx).unwrap(); + f.native(&mut store).unwrap(); - assert_eq!(*ctx.data().0.lock().unwrap(), 100); + assert_eq!(*env.as_mut(&mut store).0.lock().unwrap(), 100); - let result = f_native.call(&mut ctx, 1, 3, 5.0, 7.0)?; + let result = f_native.call(&mut store, 1, 3, 5.0, 7.0)?; assert_eq!(result, (28.0, 15.0, 6, 1)); - assert_eq!(*ctx.data().0.lock().unwrap(), 101); + assert_eq!(*env.as_mut(&mut store).0.lock().unwrap(), 101); Ok(()) } diff --git a/tests/compilers/serialize.rs b/tests/compilers/serialize.rs index 96306f0666a..1b796bf58c5 100644 --- a/tests/compilers/serialize.rs +++ b/tests/compilers/serialize.rs @@ -1,10 +1,10 @@ use anyhow::Result; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::*; #[compiler_test(serialize)] fn test_serialize(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module (func $hello (import "" "hello")) @@ -20,7 +20,7 @@ fn test_serialize(config: crate::Config) -> Result<()> { #[compiler_test(serialize)] fn test_deserialize(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module $name (import "host" "sum_part" (func (param i32 i64 i32 f32 f64) (result i64))) @@ -54,8 +54,8 @@ fn test_deserialize(config: crate::Config) -> Result<()> { vec![Type::I32, Type::I64, Type::I32, Type::F32, Type::F64], vec![Type::I64], ); - let mut ctx = WasmerContext::new(&store, ()); - let f0 = Function::new(&mut ctx, &func_type, |_ctx, params| { + let mut env = FunctionEnv::new(&mut store, ()); + let f0 = Function::new(&mut store, &env, &func_type, |_ctx, params| { let param_0: i64 = params[0].unwrap_i32() as i64; let param_1: i64 = params[1].unwrap_i64() as i64; let param_2: i64 = params[2].unwrap_i32() as i64; @@ -66,7 +66,7 @@ fn test_deserialize(config: crate::Config) -> Result<()> { )]) }); let instance = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "host" => { @@ -76,7 +76,7 @@ fn test_deserialize(config: crate::Config) -> Result<()> { )?; let test_call = instance.exports.get_function("test_call")?; - let result = test_call.call(&mut ctx, &[])?; + let result = test_call.call(&mut store, &[])?; assert_eq!(result.to_vec(), vec![Value::I64(1500)]); Ok(()) } diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index 4cf7d4226fb..fff22c69e05 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -1,11 +1,11 @@ use anyhow::Result; use std::panic::{self, AssertUnwindSafe}; -use wasmer::Context as WasmerContext; +use wasmer::FunctionEnv; use wasmer::*; #[compiler_test(traps)] fn test_trap_return(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module (func $hello (import "" "hello")) @@ -14,14 +14,14 @@ fn test_trap_return(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let hello_type = FunctionType::new(vec![], vec![]); - let hello_func = Function::new(&mut ctx, &hello_type, |_ctx, _| { + let hello_func = Function::new(&mut store, &env, &hello_type, |_ctx, _| { Err(RuntimeError::new("test 123")) }); let instance = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "" => { @@ -35,7 +35,7 @@ fn test_trap_return(config: crate::Config) -> Result<()> { .expect("expected function export"); let e = run_func - .call(&mut ctx, &[]) + .call(&mut store, &[]) .err() .expect("error calling function"); @@ -47,7 +47,7 @@ fn test_trap_return(config: crate::Config) -> Result<()> { #[cfg_attr(target_env = "musl", ignore)] #[compiler_test(traps)] fn test_trap_trace(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module $hello_mod (func (export "run") (call $hello)) @@ -55,16 +55,16 @@ fn test_trap_trace(config: crate::Config) -> Result<()> { ) "#; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let instance = Instance::new(&mut store, &module, &imports! {})?; let run_func = instance .exports .get_function("run") .expect("expected function export"); let e = run_func - .call(&mut ctx, &[]) + .call(&mut store, &[]) .err() .expect("error calling function"); @@ -87,7 +87,7 @@ fn test_trap_trace(config: crate::Config) -> Result<()> { #[compiler_test(traps)] fn test_trap_trace_cb(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module $hello_mod (import "" "throw" (func $throw)) @@ -96,15 +96,15 @@ fn test_trap_trace_cb(config: crate::Config) -> Result<()> { ) "#; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let fn_type = FunctionType::new(vec![], vec![]); - let fn_func = Function::new(&mut ctx, &fn_type, |_ctx, _| { + let fn_func = Function::new(&mut store, &env, &fn_type, |_ctx, _| { Err(RuntimeError::new("cb throw")) }); let module = Module::new(&store, wat)?; let instance = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "" => { @@ -118,7 +118,7 @@ fn test_trap_trace_cb(config: crate::Config) -> Result<()> { .expect("expected function export"); let e = run_func - .call(&mut ctx, &[]) + .call(&mut store, &[]) .err() .expect("error calling function"); @@ -138,7 +138,7 @@ fn test_trap_trace_cb(config: crate::Config) -> Result<()> { #[cfg_attr(target_env = "musl", ignore)] #[compiler_test(traps)] fn test_trap_stack_overflow(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module $rec_mod (func $run (export "run") (call $run)) @@ -146,15 +146,15 @@ fn test_trap_stack_overflow(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let mut ctx = WasmerContext::new(&store, ()); - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let mut env = FunctionEnv::new(&mut store, ()); + let instance = Instance::new(&mut store, &module, &imports! {})?; let run_func = instance .exports .get_function("run") .expect("expected function export"); let e = run_func - .call(&mut ctx, &[]) + .call(&mut store, &[]) .err() .expect("error calling function"); @@ -169,7 +169,7 @@ fn test_trap_stack_overflow(config: crate::Config) -> Result<()> { #[cfg_attr(target_env = "musl", ignore)] #[compiler_test(traps)] fn trap_display_pretty(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module $m (func $die unreachable) @@ -180,15 +180,15 @@ fn trap_display_pretty(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let mut ctx = WasmerContext::new(&store, ()); - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let mut env = FunctionEnv::new(&mut store, ()); + let instance = Instance::new(&mut store, &module, &imports! {})?; let run_func = instance .exports .get_function("bar") .expect("expected function export"); let e = run_func - .call(&mut ctx, &[]) + .call(&mut store, &[]) .err() .expect("error calling function"); assert_eq!( @@ -206,7 +206,7 @@ RuntimeError: unreachable #[cfg_attr(target_env = "musl", ignore)] #[compiler_test(traps)] fn trap_display_multi_module(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module $a (func $die unreachable) @@ -217,8 +217,8 @@ fn trap_display_multi_module(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let mut ctx = WasmerContext::new(&store, ()); - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let mut env = FunctionEnv::new(&mut store, ()); + let instance = Instance::new(&mut store, &module, &imports! {})?; let bar = instance.exports.get_function("bar")?.clone(); let wat = r#" @@ -230,7 +230,7 @@ fn trap_display_multi_module(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; let instance = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "" => { @@ -244,7 +244,7 @@ fn trap_display_multi_module(config: crate::Config) -> Result<()> { .expect("expected function export"); let e = bar2 - .call(&mut ctx, &[]) + .call(&mut store, &[]) .err() .expect("error calling function"); assert_eq!( @@ -263,7 +263,7 @@ RuntimeError: unreachable #[compiler_test(traps)] fn trap_start_function_import(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let binary = r#" (module $a (import "" "" (func $foo)) @@ -272,13 +272,13 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let sig = FunctionType::new(vec![], vec![]); - let func = Function::new(&mut ctx, &sig, |_ctx, _| { + let func = Function::new(&mut store, &env, &sig, |_ctx, _| { Err(RuntimeError::new("user trap")) }); let err = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "" => { @@ -290,7 +290,7 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> { .unwrap(); match err { InstantiationError::Link(_) - | InstantiationError::BadContext + | InstantiationError::DifferentStores | InstantiationError::CpuFeature(_) => { panic!("It should be a start error") } @@ -304,7 +304,7 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> { #[compiler_test(traps)] fn rust_panic_import(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let binary = r#" (module $a (import "" "foo" (func $foo)) @@ -315,14 +315,14 @@ fn rust_panic_import(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let sig = FunctionType::new(vec![], vec![]); - let func = Function::new(&mut ctx, &sig, |_ctx, _| panic!("this is a panic")); - let f0 = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + let func = Function::new(&mut store, &env, &sig, |_ctx, _| panic!("this is a panic")); + let f0 = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<_>| { panic!("this is another panic") }); let instance = Instance::new( - &mut ctx, + &mut store, &module, &imports! { "" => { @@ -333,7 +333,7 @@ fn rust_panic_import(config: crate::Config) -> Result<()> { )?; let func = instance.exports.get_function("foo")?.clone(); let err = panic::catch_unwind(AssertUnwindSafe(|| { - drop(func.call(&mut ctx, &[])); + drop(func.call(&mut store, &[])); })) .unwrap_err(); assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic")); @@ -354,7 +354,7 @@ fn rust_panic_import(config: crate::Config) -> Result<()> { #[compiler_test(traps)] fn rust_panic_start_function(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let binary = r#" (module $a (import "" "" (func $foo)) @@ -363,12 +363,12 @@ fn rust_panic_start_function(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; - let mut ctx = WasmerContext::new(&store, ()); + let mut env = FunctionEnv::new(&mut store, ()); let sig = FunctionType::new(vec![], vec![]); - let func = Function::new(&mut ctx, &sig, |_ctx, _| panic!("this is a panic")); + let func = Function::new(&mut store, &env, &sig, |_ctx, _| panic!("this is a panic")); let err = panic::catch_unwind(AssertUnwindSafe(|| { drop(Instance::new( - &mut ctx, + &mut store, &module, &imports! { "" => { @@ -380,12 +380,12 @@ fn rust_panic_start_function(config: crate::Config) -> Result<()> { .unwrap_err(); assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic")); - let func = Function::new_native(&mut ctx, |_ctx: ContextMut<_>| { + let func = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<_>| { panic!("this is another panic") }); let err = panic::catch_unwind(AssertUnwindSafe(|| { drop(Instance::new( - &mut ctx, + &mut store, &module, &imports! { "" => { @@ -404,7 +404,7 @@ fn rust_panic_start_function(config: crate::Config) -> Result<()> { #[compiler_test(traps)] fn mismatched_arguments(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let binary = r#" (module $a (func (export "foo") (param i32)) @@ -412,21 +412,21 @@ fn mismatched_arguments(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; - let mut ctx = WasmerContext::new(&store, ()); - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let mut env = FunctionEnv::new(&mut store, ()); + let instance = Instance::new(&mut store, &module, &imports! {})?; let func: &Function = instance.exports.get("foo")?; assert_eq!( - func.call(&mut ctx, &[]).unwrap_err().message(), + func.call(&mut store, &[]).unwrap_err().message(), "Parameters of type [] did not match signature [I32] -> []" ); assert_eq!( - func.call(&mut ctx, &[Value::F32(0.0)]) + func.call(&mut store, &[Value::F32(0.0)]) .unwrap_err() .message(), "Parameters of type [F32] did not match signature [I32] -> []", ); assert_eq!( - func.call(&mut ctx, &[Value::I32(0), Value::I32(1)]) + func.call(&mut store, &[Value::I32(0), Value::I32(1)]) .unwrap_err() .message(), "Parameters of type [I32, I32] did not match signature [I32] -> []" @@ -437,7 +437,7 @@ fn mismatched_arguments(config: crate::Config) -> Result<()> { #[cfg_attr(target_env = "musl", ignore)] #[compiler_test(traps)] fn call_signature_mismatch(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let binary = r#" (module $a (func $foo @@ -452,8 +452,8 @@ fn call_signature_mismatch(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, &binary)?; - let mut ctx = WasmerContext::new(&store, ()); - let err = Instance::new(&mut ctx, &module, &imports! {}) + let mut env = FunctionEnv::new(&mut store, ()); + let err = Instance::new(&mut store, &module, &imports! {}) .err() .expect("expected error"); assert_eq!( @@ -469,7 +469,7 @@ RuntimeError: indirect call type mismatch #[compiler_test(traps)] #[cfg_attr(target_env = "musl", ignore)] fn start_trap_pretty(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let wat = r#" (module $m (func $die unreachable) @@ -481,8 +481,8 @@ fn start_trap_pretty(config: crate::Config) -> Result<()> { "#; let module = Module::new(&store, wat)?; - let mut ctx = WasmerContext::new(&store, ()); - let err = Instance::new(&mut ctx, &module, &imports! {}) + let mut env = FunctionEnv::new(&mut store, ()); + let err = Instance::new(&mut store, &module, &imports! {}) .err() .expect("expected error"); @@ -501,18 +501,18 @@ RuntimeError: unreachable #[compiler_test(traps)] fn present_after_module_drop(config: crate::Config) -> Result<()> { - let store = config.store(); + let mut store = config.store(); let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?; - let mut ctx = WasmerContext::new(&store, ()); - let instance = Instance::new(&mut ctx, &module, &imports! {})?; + let mut env = FunctionEnv::new(&mut store, ()); + let instance = Instance::new(&mut store, &module, &imports! {})?; let func: Function = instance.exports.get_function("foo")?.clone(); println!("asserting before we drop modules"); - assert_trap(func.call(&mut ctx, &[]).unwrap_err()); + assert_trap(func.call(&mut store, &[]).unwrap_err()); drop((instance, module)); println!("asserting after drop"); - assert_trap(func.call(&mut ctx, &[]).unwrap_err()); + assert_trap(func.call(&mut store, &[]).unwrap_err()); return Ok(()); fn assert_trap(t: RuntimeError) { diff --git a/tests/compilers/wasi.rs b/tests/compilers/wasi.rs index be339e3db78..ffe37657c3e 100644 --- a/tests/compilers/wasi.rs +++ b/tests/compilers/wasi.rs @@ -23,7 +23,7 @@ pub fn run_wasi( filesystem_kind: WasiFileSystemKind, ) -> anyhow::Result<()> { println!("Running wasi wast `{}`", wast_path); - let store = config.store(); + let mut store = config.store(); let source = { let mut out = String::new(); @@ -34,7 +34,7 @@ pub fn run_wasi( let tokens = WasiTest::lex_string(&source)?; let wasi_test = WasiTest::parse_tokens(&tokens)?; - let succeeded = wasi_test.run(&store, base_dir, filesystem_kind)?; + let succeeded = wasi_test.run(&mut store, base_dir, filesystem_kind)?; assert!(succeeded); diff --git a/tests/compilers/wast.rs b/tests/compilers/wast.rs index 0910c279867..0f6e3f36cb9 100644 --- a/tests/compilers/wast.rs +++ b/tests/compilers/wast.rs @@ -1,4 +1,4 @@ -use ::wasmer::{Context, Features}; +use ::wasmer::Features; use std::path::Path; use wasmer_wast::Wast; @@ -34,9 +34,8 @@ pub fn run_wast(mut config: crate::Config, wast_path: &str) -> anyhow::Result<() config.set_features(features); config.set_nan_canonicalization(try_nan_canonicalization); - let store = config.store(); - let context = Context::new(&store, ()); - let mut wast = Wast::new_with_spectest(context); + let mut store = config.store(); + let mut wast = Wast::new_with_spectest(store); // `bulk-memory-operations/bulk.wast` checks for a message that // specifies which element is uninitialized, but our traps don't // shepherd that information out. diff --git a/tests/lib/wast/src/spectest.rs b/tests/lib/wast/src/spectest.rs index 36d0d848a36..389a5c4e16c 100644 --- a/tests/lib/wast/src/spectest.rs +++ b/tests/lib/wast/src/spectest.rs @@ -2,39 +2,41 @@ use wasmer::*; /// Return an instance implementing the "spectest" interface used in the /// spec testsuite. -pub fn spectest_importobject(context: &mut Context<()>) -> Imports { - let print = Function::new_native(context, |_: ContextMut<'_, ()>| {}); - let print_i32 = Function::new_native(context, |_: ContextMut<'_, ()>, val: i32| { +pub fn spectest_importobject(store: &mut Store, context: &FunctionEnv<()>) -> Imports { + let print = Function::new_native(store, context, |_: FunctionEnvMut<()>| {}); + let print_i32 = Function::new_native(store, context, |_: FunctionEnvMut<()>, val: i32| { println!("{}: i32", val) }); - let print_i64 = Function::new_native(context, |_: ContextMut<'_, ()>, val: i64| { + let print_i64 = Function::new_native(store, context, |_: FunctionEnvMut<()>, val: i64| { println!("{}: i64", val) }); - let print_f32 = Function::new_native(context, |_: ContextMut<'_, ()>, val: f32| { + let print_f32 = Function::new_native(store, context, |_: FunctionEnvMut<()>, val: f32| { println!("{}: f32", val) }); - let print_f64 = Function::new_native(context, |_: ContextMut<'_, ()>, val: f64| { + let print_f64 = Function::new_native(store, context, |_: FunctionEnvMut<()>, val: f64| { println!("{}: f64", val) }); - let print_i32_f32 = Function::new_native(context, |_: ContextMut<'_, ()>, i: i32, f: f32| { - println!("{}: i32", i); - println!("{}: f32", f); - }); - let print_f64_f64 = Function::new_native(context, |_: ContextMut<'_, ()>, f1: f64, f2: f64| { - println!("{}: f64", f1); - println!("{}: f64", f2); - }); + let print_i32_f32 = + Function::new_native(store, context, |_: FunctionEnvMut<()>, i: i32, f: f32| { + println!("{}: i32", i); + println!("{}: f32", f); + }); + let print_f64_f64 = + Function::new_native(store, context, |_: FunctionEnvMut<()>, f1: f64, f2: f64| { + println!("{}: f64", f1); + println!("{}: f64", f2); + }); - let global_i32 = Global::new(context, Value::I32(666)); - let global_i64 = Global::new(context, Value::I64(666)); - let global_f32 = Global::new(context, Value::F32(f32::from_bits(0x4426_8000))); - let global_f64 = Global::new(context, Value::F64(f64::from_bits(0x4084_d000_0000_0000))); + let global_i32 = Global::new(store, Value::I32(666)); + let global_i64 = Global::new(store, Value::I64(666)); + let global_f32 = Global::new(store, Value::F32(f32::from_bits(0x4426_8000))); + let global_f64 = Global::new(store, Value::F64(f64::from_bits(0x4084_d000_0000_0000))); let ty = TableType::new(Type::FuncRef, 10, Some(20)); - let table = Table::new(context, ty, Value::FuncRef(None)).unwrap(); + let table = Table::new(store, ty, Value::FuncRef(None)).unwrap(); let ty = MemoryType::new(1, Some(2), false); - let memory = Memory::new(context, ty).unwrap(); + let memory = Memory::new(store, ty).unwrap(); imports! { "spectest" => { diff --git a/tests/lib/wast/src/wasi_wast.rs b/tests/lib/wast/src/wasi_wast.rs index a9934ec3f14..6b2e13aac4c 100644 --- a/tests/lib/wast/src/wasi_wast.rs +++ b/tests/lib/wast/src/wasi_wast.rs @@ -3,13 +3,13 @@ use std::fs::{read_dir, File, OpenOptions, ReadDir}; use std::io::{self, Read, Seek, Write}; use std::path::{Path, PathBuf}; use std::sync::{mpsc, Arc, Mutex}; -use wasmer::Context as WasmerContext; -use wasmer::{AsContextMut, ContextMut, Imports, Instance, Module, Store}; +use wasmer::FunctionEnv; +use wasmer::{Imports, Instance, Module, Store}; use wasmer_vfs::{host_fs, mem_fs, FileSystem}; use wasmer_wasi::types::{__wasi_filesize_t, __wasi_timestamp_t}; use wasmer_wasi::{ - generate_import_object_from_ctx, get_wasi_version, FsError, Pipe, VirtualFile, WasiEnv, - WasiState, WasiVersion, + generate_import_object_from_env, get_wasi_version, FsError, Pipe, VirtualFile, WasiEnv, + WasiFunctionEnv, WasiState, WasiVersion, }; use wast::parser::{self, Parse, ParseBuffer, Parser}; @@ -70,7 +70,7 @@ impl<'a> WasiTest<'a> { /// Execute the WASI test and assert. pub fn run( &self, - store: &Store, + mut store: &mut Store, base_path: &str, filesystem_kind: WasiFileSystemKind, ) -> anyhow::Result { @@ -83,24 +83,25 @@ impl<'a> WasiTest<'a> { out }; let module = Module::new(store, &wasm_bytes)?; - let (env, _tempdirs, stdout_rx, stderr_rx) = self.create_wasi_env(filesystem_kind)?; - let mut ctx = WasmerContext::new(store, env.clone()); - let imports = self.get_imports(&mut ctx.as_context_mut(), &module)?; - let instance = Instance::new(&mut ctx, &module, &imports)?; + let (env, _tempdirs, stdout_rx, stderr_rx) = + self.create_wasi_env(store, filesystem_kind)?; + let imports = self.get_imports(store, &env.env, &module)?; + let instance = Instance::new(&mut store, &module, &imports)?; let start = instance.exports.get_function("_start")?; let memory = instance.exports.get_memory("memory")?; - ctx.data_mut().set_memory(memory.clone()); + let wasi_env = env.data_mut(&mut store); + wasi_env.set_memory(memory.clone()); if let Some(stdin) = &self.stdin { - let state = env.state(); + let state = wasi_env.state(); let mut wasi_stdin = state.stdin().unwrap().unwrap(); // Then we can write to it! write!(wasi_stdin, "{}", stdin.stream)?; } // TODO: handle errors here when the error fix gets shipped - match start.call(&mut ctx, &[]) { + match start.call(&mut store, &[]) { Ok(_) => {} Err(e) => { let stdout_str = get_stdio_output(&stdout_rx)?; @@ -132,9 +133,10 @@ impl<'a> WasiTest<'a> { #[allow(clippy::type_complexity)] fn create_wasi_env( &self, + mut store: &mut Store, filesystem_kind: WasiFileSystemKind, ) -> anyhow::Result<( - WasiEnv, + WasiFunctionEnv, Vec, mpsc::Receiver>, mpsc::Receiver>, @@ -217,7 +219,7 @@ impl<'a> WasiTest<'a> { //.env("RUST_BACKTRACE", "1") .stdout(Box::new(stdout)) .stderr(Box::new(stderr)) - .finalize()?; + .finalize(&mut store)?; Ok((out, host_temp_dirs_to_not_drop, stdout_rx, stderr_rx)) } @@ -233,11 +235,12 @@ impl<'a> WasiTest<'a> { /// [`WasiEnv`]. fn get_imports( &self, - ctx: &mut ContextMut<'_, WasiEnv>, + store: &mut Store, + ctx: &FunctionEnv, module: &Module, ) -> anyhow::Result { let version = self.get_version(module)?; - Ok(generate_import_object_from_ctx(ctx, version)) + Ok(generate_import_object_from_env(store, ctx, version)) } } diff --git a/tests/lib/wast/src/wast.rs b/tests/lib/wast/src/wast.rs index 3eb689b40b8..89fb7e08314 100644 --- a/tests/lib/wast/src/wast.rs +++ b/tests/lib/wast/src/wast.rs @@ -8,6 +8,7 @@ use wasmer::*; /// The wast test script language allows modules to be defined and actions /// to be performed on them. +#[allow(dead_code)] pub struct Wast { /// Wast files have a concept of a "current" module, which is the most /// recently defined. @@ -23,8 +24,10 @@ pub struct Wast { match_trap_messages: HashMap, /// If the current module was an allowed failure, we allow test to fail current_is_allowed_failure: bool, + /// The store in which the tests are executing. + store: Store, /// The context in which the tests are executing. - context: Context<()>, + context: FunctionEnv<()>, /// A flag indicating if Wast tests should stop as soon as one test fails. pub fail_fast: bool, /// A flag indicating that assert_trap and assert_exhaustion should be skipped. @@ -34,9 +37,10 @@ pub struct Wast { impl Wast { /// Construct a new instance of `Wast` with a given imports. - pub fn new(context: Context<()>, import_object: Imports) -> Self { + pub fn new(store: Store, context: FunctionEnv<()>, import_object: Imports) -> Self { Self { current: None, + store, context, import_object, allowed_instantiation_failures: HashSet::new(), @@ -68,9 +72,10 @@ impl Wast { } /// Construct a new instance of `Wast` with the spectests imports. - pub fn new_with_spectest(mut context: Context<()>) -> Self { - let import_object = spectest_importobject(&mut context); - Self::new(context, import_object) + pub fn new_with_spectest(mut store: Store) -> Self { + let context = FunctionEnv::new(&mut store, ()); + let import_object = spectest_importobject(&mut store, &context); + Self::new(store, context, import_object) } fn get_instance(&self, instance_name: Option<&str>) -> Result { @@ -366,7 +371,7 @@ impl Wast { } fn instantiate(&mut self, module: &[u8]) -> Result { - let module = Module::new(self.context.store(), module)?; + let module = Module::new(&self.store, module)?; let mut imports = self.import_object.clone(); for import in module.imports() { @@ -381,7 +386,7 @@ impl Wast { imports.register_namespace(module_name, instance.exports.clone()); } - let instance = Instance::new(&mut self.context, &module, &imports)?; + let instance = Instance::new(&mut self.store, &module, &imports)?; Ok(instance) } @@ -401,7 +406,7 @@ impl Wast { ) -> Result> { let instance = self.get_instance(instance_name)?; let func: &Function = instance.exports.get(field)?; - match func.call(&mut self.context, args) { + match func.call(&mut self.store, args) { Ok(result) => Ok(result.into()), Err(e) => Err(e.into()), } @@ -411,7 +416,7 @@ impl Wast { fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result> { let instance = self.get_instance(instance_name)?; let global: &Global = instance.exports.get(field)?; - Ok(vec![global.get(&mut self.context)]) + Ok(vec![global.get(&mut self.store)]) } /// Translate from a `script::Value` to a `Value`. @@ -429,7 +434,7 @@ impl Wast { V128Const(x) => Value::V128(u128::from_le_bytes(x.to_le_bytes())), RefNull(wast::HeapType::Func) => Value::FuncRef(None), RefNull(wast::HeapType::Extern) => Value::null(), - RefExtern(number) => Value::ExternRef(Some(ExternRef::new(&mut self.context, *number))), + RefExtern(number) => Value::ExternRef(Some(ExternRef::new(&mut self.store, *number))), other => bail!("couldn't convert {:?} to a runtime value", other), }) } @@ -489,7 +494,7 @@ impl Wast { (Value::ExternRef(Some(_)), wast::AssertExpression::RefNull(_)) => false, (Value::ExternRef(Some(extern_ref)), wast::AssertExpression::RefExtern(num)) => { - extern_ref.downcast(&self.context) == Some(num) + extern_ref.downcast(&self.store) == Some(num) } _ => bail!( "don't know how to compare {:?} and {:?} yet", From 97732351d4e5357643fd8609a14637f9faf8b7ed Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Wed, 13 Jul 2022 15:46:42 +0200 Subject: [PATCH 24/24] Added back Memory::data_unchecked and Memory::data_unchecked_mut as hidden (for wit-bindgen) --- lib/api/src/sys/externals/memory.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/api/src/sys/externals/memory.rs b/lib/api/src/sys/externals/memory.rs index 45b093c5070..ae682740452 100644 --- a/lib/api/src/sys/externals/memory.rs +++ b/lib/api/src/sys/externals/memory.rs @@ -86,6 +86,33 @@ impl Memory { self.buffer(ctx).len.try_into().unwrap() } + /// Retrieve a slice of the memory contents. + /// + /// # Safety + /// + /// Until the returned slice is dropped, it is undefined behaviour to + /// modify the memory contents in any way including by calling a wasm + /// function that writes to the memory or by resizing the memory. + #[doc(hidden)] + pub unsafe fn data_unchecked(&self, ctx: &impl AsStoreRef) -> &[u8] { + self.data_unchecked_mut(ctx) + } + + /// Retrieve a mutable slice of the memory contents. + /// + /// # Safety + /// + /// This method provides interior mutability without an UnsafeCell. Until + /// the returned value is dropped, it is undefined behaviour to read or + /// write to the pointed-to memory in any way except through this slice, + /// including by calling a wasm function that reads the memory contents or + /// by resizing this Memory. + #[allow(clippy::mut_from_ref)] + #[doc(hidden)] + pub unsafe fn data_unchecked_mut(&self, ctx: &impl AsStoreRef) -> &mut [u8] { + slice::from_raw_parts_mut(self.buffer(ctx).base, self.buffer(ctx).len) + } + /// Returns the size (in [`Pages`]) of the `Memory`. /// /// # Example