From 6aa87a0bbf2e6f4e02f75e5d96e0d46345c2973d Mon Sep 17 00:00:00 2001 From: losfair Date: Fri, 17 May 2019 01:10:21 +0800 Subject: [PATCH 1/5] Add the `internals` field and necessary structures for metering. --- lib/llvm-backend/src/code.rs | 1 + lib/llvm-backend/src/intrinsics.rs | 4 ++++ lib/runtime-core/src/backing.rs | 19 ++++++++++++++++++- lib/runtime-core/src/codegen.rs | 5 ++++- lib/runtime-core/src/lib.rs | 2 ++ lib/runtime-core/src/vm.rs | 19 +++++++++++++++++-- 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/lib/llvm-backend/src/code.rs b/lib/llvm-backend/src/code.rs index 8514208ad54..aecf6fd74ae 100644 --- a/lib/llvm-backend/src/code.rs +++ b/lib/llvm-backend/src/code.rs @@ -472,6 +472,7 @@ impl FunctionCodeGenerator for LLVMFunctionCodeGenerator { fn feed_event(&mut self, event: Event, module_info: &ModuleInfo) -> Result<(), CodegenError> { let op = match event { Event::Wasm(x) => x, + Event::WasmOwned(ref x) => x, Event::Internal(_x) => { return Ok(()); } diff --git a/lib/llvm-backend/src/intrinsics.rs b/lib/llvm-backend/src/intrinsics.rs index ebee5a3882d..2198821ed9f 100644 --- a/lib/llvm-backend/src/intrinsics.rs +++ b/lib/llvm-backend/src/intrinsics.rs @@ -163,6 +163,7 @@ impl Intrinsics { let stack_lower_bound_ty = i8_ty; let memory_base_ty = i8_ty; let memory_bound_ty = void_ty; + let internals_ty = void_ty; let local_function_ty = i8_ptr_ty; let anyfunc_ty = context.struct_type( @@ -218,6 +219,9 @@ impl Intrinsics { memory_bound_ty .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), + internals_ty + .ptr_type(AddressSpace::Generic) + .as_basic_type_enum(), local_function_ty .ptr_type(AddressSpace::Generic) .as_basic_type_enum(), diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 821ff379f4d..52aec386eaa 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -15,7 +15,20 @@ use crate::{ }, vm, }; -use std::slice; +use std::{ + slice, + fmt::Debug, +}; + +pub const INTERNALS_SIZE: usize = 256; + +pub(crate) struct Internals(pub(crate) [u64; INTERNALS_SIZE]); + +impl Debug for Internals { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(formatter, "Internals({:?})", &self.0[..]) + } +} /// The `LocalBacking` "owns" the memory used by all the local resources of an Instance. /// That is, local memories, tables, and globals (as well as some additional @@ -40,6 +53,8 @@ pub struct LocalBacking { /// as well) are subject to change. pub(crate) dynamic_sigindices: BoxedMap, pub(crate) local_functions: BoxedMap, + + pub(crate) internals: Internals, } impl LocalBacking { @@ -66,6 +81,8 @@ impl LocalBacking { dynamic_sigindices, local_functions, + + internals: Internals([0; 256]), } } diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index 1d9f30f1a4e..9ae20d8c942 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -17,6 +17,7 @@ use wasmparser::{Operator, Type as WpType}; pub enum Event<'a, 'b> { Internal(InternalEvent), Wasm(&'b Operator<'a>), + WasmOwned(Operator<'a>), } pub enum InternalEvent { @@ -39,7 +40,9 @@ impl fmt::Debug for InternalEvent { } } -pub struct BkptInfo {} +pub struct BkptInfo { + pub throw: unsafe extern "C" fn () -> !, +} pub trait ModuleCodeGenerator, RM: RunnableModule, E: Debug> { /// Creates a new module code generator. diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 20708c17a5e..871e5875b6e 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -49,6 +49,8 @@ pub use self::module::Module; pub use self::typed_func::Func; use std::sync::Arc; +pub use wasmparser; + use self::cache::{Artifact, Error as CacheError}; pub mod prelude { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 323e40c219b..b772cc9b479 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -1,4 +1,4 @@ -pub use crate::backing::{ImportBacking, LocalBacking}; +pub use crate::backing::{ImportBacking, LocalBacking, INTERNALS_SIZE}; use crate::{ memory::{Memory, MemoryType}, module::{ModuleInfo, ModuleInner}, @@ -92,6 +92,8 @@ pub struct InternalCtx { pub memory_base: *mut u8, pub memory_bound: usize, + + pub internals: *mut [u64; INTERNALS_SIZE], // TODO: Make this dynamic? } #[repr(C)] @@ -200,6 +202,8 @@ impl Ctx { memory_base: mem_base, memory_bound: mem_bound, + + internals: &mut local_backing.internals.0, }, local_functions: local_backing.local_functions.as_ptr(), @@ -249,6 +253,8 @@ impl Ctx { memory_base: mem_base, memory_bound: mem_bound, + + internals: &mut local_backing.internals.0, }, local_functions: local_backing.local_functions.as_ptr(), @@ -356,9 +362,13 @@ impl Ctx { 11 * (mem::size_of::() as u8) } - pub fn offset_local_functions() -> u8 { + pub fn offset_internals() -> u8 { 12 * (mem::size_of::() as u8) } + + pub fn offset_local_functions() -> u8 { + 13 * (mem::size_of::() as u8) + } } enum InnerFunc {} @@ -572,6 +582,11 @@ mod vm_offset_tests { offset_of!(InternalCtx => memory_bound).get_byte_offset(), ); + assert_eq!( + Ctx::offset_internals() as usize, + offset_of!(InternalCtx => internals).get_byte_offset(), + ); + assert_eq!( Ctx::offset_local_functions() as usize, offset_of!(Ctx => local_functions).get_byte_offset(), From 7e79dd2cfe20b81ea466bbe440988cbc9d9282bc Mon Sep 17 00:00:00 2001 From: losfair Date: Fri, 17 May 2019 01:10:45 +0800 Subject: [PATCH 2/5] Metering middleware. --- lib/middleware-common/Cargo.toml | 2 +- lib/middleware-common/src/lib.rs | 1 + lib/middleware-common/src/metering.rs | 83 +++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 lib/middleware-common/src/metering.rs diff --git a/lib/middleware-common/Cargo.toml b/lib/middleware-common/Cargo.toml index 57a42577ccc..2beabfb6b3d 100644 --- a/lib/middleware-common/Cargo.toml +++ b/lib/middleware-common/Cargo.toml @@ -8,4 +8,4 @@ authors = ["The Wasmer Engineering Team "] edition = "2018" [dependencies] -wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" } +wasmer-runtime-core = { path = "../runtime-core" } diff --git a/lib/middleware-common/src/lib.rs b/lib/middleware-common/src/lib.rs index e09d9ee03b7..41699c9e705 100644 --- a/lib/middleware-common/src/lib.rs +++ b/lib/middleware-common/src/lib.rs @@ -1,3 +1,4 @@ #![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)] pub mod call_trace; +pub mod metering; diff --git a/lib/middleware-common/src/metering.rs b/lib/middleware-common/src/metering.rs new file mode 100644 index 00000000000..5d19eef353e --- /dev/null +++ b/lib/middleware-common/src/metering.rs @@ -0,0 +1,83 @@ +use wasmer_runtime_core::{ + codegen::{Event, EventSink, FunctionMiddleware, InternalEvent}, + module::ModuleInfo, + wasmparser::{Operator, Type as WpType}, +}; + +pub struct Metering { + limit: u64, + current_block: u64, +} + +impl Metering { + pub fn new(limit: u64) -> Metering { + Metering { + limit, + current_block: 0, + } + } +} + +impl FunctionMiddleware for Metering { + type Error = String; + fn feed_event<'a, 'b: 'a>( + &mut self, + op: Event<'a, 'b>, + _module_info: &ModuleInfo, + sink: &mut EventSink<'a, 'b>, + ) -> Result<(), Self::Error> { + match op { + Event::Internal(InternalEvent::FunctionBegin(_)) => { + self.current_block = 0; + }, + Event::Wasm(&ref op) | Event::WasmOwned(ref op) => { + self.current_block += 1; + match *op { + Operator::Loop { .. } + | Operator::Block { .. } + | Operator::End + | Operator::If { .. } + | Operator::Else + | Operator::Unreachable + | Operator::Br { .. } + | Operator::BrTable { .. } + | Operator::BrIf { .. } + | Operator::Call { .. } + | Operator::CallIndirect { .. } + => { + sink.push(Event::Internal(InternalEvent::GetInternal(0))); + sink.push(Event::WasmOwned(Operator::I64Const { value: self.current_block as i64 })); + sink.push(Event::WasmOwned(Operator::I64Add)); + sink.push(Event::Internal(InternalEvent::SetInternal(0))); + self.current_block = 0; + }, + _ => {} + } + match *op { + Operator::Br { .. } + | Operator::BrTable { .. } + | Operator::BrIf { .. } + | Operator::Call { .. } + | Operator::CallIndirect { .. } + => { + sink.push(Event::Internal(InternalEvent::GetInternal(0))); + sink.push(Event::WasmOwned(Operator::I64Const { value: self.limit as i64 })); + sink.push(Event::WasmOwned(Operator::I64GeU)); + sink.push(Event::WasmOwned(Operator::If { ty: WpType::EmptyBlockType })); + sink.push(Event::Internal(InternalEvent::Breakpoint(Box::new(move |ctx| { + eprintln!("execution limit reached"); + unsafe { + (ctx.throw)(); + } + })))); + sink.push(Event::WasmOwned(Operator::End)); + }, + _ => {} + } + }, + _ => {} + } + sink.push(op); + Ok(()) + } +} From e7297b9465f131c0dea9fb2e69378d6809f33f3a Mon Sep 17 00:00:00 2001 From: losfair Date: Fri, 17 May 2019 01:11:22 +0800 Subject: [PATCH 3/5] Update singlepass backend to support metering. --- lib/singlepass-backend/src/codegen_x64.rs | 71 +++++++++++++++++++++- lib/singlepass-backend/src/protect_unix.rs | 12 +++- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index 7d4d0de5cc1..4a0c3e4f5f1 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -23,7 +23,7 @@ use wasmer_runtime_core::{ FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type, }, - vm::{self, LocalGlobal, LocalTable}, + vm::{self, LocalGlobal, LocalTable, INTERNALS_SIZE}, }; use wasmparser::{Operator, Type as WpType}; @@ -1494,8 +1494,10 @@ impl FunctionCodeGenerator for X64FunctionCode { let a = self.assembler.as_mut().unwrap(); + let op = match ev { Event::Wasm(x) => x, + Event::WasmOwned(ref x) => x, Event::Internal(x) => { match x { InternalEvent::Breakpoint(callback) => { @@ -1505,8 +1507,71 @@ impl FunctionCodeGenerator for X64FunctionCode { .unwrap() .insert(a.get_offset(), callback); } - InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {} - _ => unimplemented!(), + InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {}, + InternalEvent::GetInternal(idx) => { + let idx = idx as usize; + assert!(idx < INTERNALS_SIZE); + + let tmp = self.machine.acquire_temp_gpr().unwrap(); + + // Load `internals` pointer. + a.emit_mov( + Size::S64, + Location::Memory( + Machine::get_vmctx_reg(), + vm::Ctx::offset_internals() as i32, + ), + Location::GPR(tmp), + ); + + let loc = self.machine.acquire_locations( + a, + &[WpType::I64], + false, + )[0]; + self.value_stack.push((loc, LocalOrTemp::Temp)); + + // Move internal into the result location. + Self::emit_relaxed_binop( + a, + &mut self.machine, + Assembler::emit_mov, + Size::S64, + Location::Memory(tmp, (idx * 8) as i32), + loc, + ); + + self.machine.release_temp_gpr(tmp); + } + InternalEvent::SetInternal(idx) => { + let idx = idx as usize; + assert!(idx < INTERNALS_SIZE); + + let tmp = self.machine.acquire_temp_gpr().unwrap(); + + // Load `internals` pointer. + a.emit_mov( + Size::S64, + Location::Memory( + Machine::get_vmctx_reg(), + vm::Ctx::offset_internals() as i32, + ), + Location::GPR(tmp), + ); + let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap()); + + // Move internal into storage. + Self::emit_relaxed_binop( + a, + &mut self.machine, + Assembler::emit_mov, + Size::S64, + loc, + Location::Memory(tmp, (idx * 8) as i32), + ); + self.machine.release_temp_gpr(tmp); + } + //_ => unimplemented!(), } return Ok(()); } diff --git a/lib/singlepass-backend/src/protect_unix.rs b/lib/singlepass-backend/src/protect_unix.rs index 6204134a721..e26467b8e05 100644 --- a/lib/singlepass-backend/src/protect_unix.rs +++ b/lib/singlepass-backend/src/protect_unix.rs @@ -35,7 +35,9 @@ extern "C" fn signal_trap_handler( let bkpt_map = BKPT_MAP.with(|x| x.borrow().last().map(|x| x.clone())); if let Some(bkpt_map) = bkpt_map { if let Some(ref x) = bkpt_map.get(&(ip as usize)) { - (x)(BkptInfo {}); + (x)(BkptInfo { + throw: throw, + }); return; } } @@ -128,6 +130,14 @@ pub fn call_protected(f: impl FnOnce() -> T) -> Result { } } +pub unsafe extern "C" fn throw() -> ! { + let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get()); + if *jmp_buf == [0; SETJMP_BUFFER_LEN] { + ::std::process::abort(); + } + longjmp(jmp_buf as *mut ::nix::libc::c_void, 0xffff); +} + /// Unwinds to last protected_call. pub unsafe fn do_unwind(signum: i32, siginfo: *const c_void, ucontext: *const c_void) -> ! { // Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.) From 14fcd78b30134095e341aa76ac56fa510f32ed34 Mon Sep 17 00:00:00 2001 From: losfair Date: Fri, 17 May 2019 01:15:05 +0800 Subject: [PATCH 4/5] Update bin/wasmer and run cargo fmt. --- lib/middleware-common/src/metering.rs | 72 ++++++++++++---------- lib/runtime-core/src/backing.rs | 5 +- lib/runtime-core/src/codegen.rs | 2 +- lib/singlepass-backend/src/codegen_x64.rs | 1 - lib/singlepass-backend/src/protect_unix.rs | 4 +- src/bin/wasmer.rs | 20 +++++- 6 files changed, 60 insertions(+), 44 deletions(-) diff --git a/lib/middleware-common/src/metering.rs b/lib/middleware-common/src/metering.rs index 5d19eef353e..0b95e5f978c 100644 --- a/lib/middleware-common/src/metering.rs +++ b/lib/middleware-common/src/metering.rs @@ -29,52 +29,58 @@ impl FunctionMiddleware for Metering { match op { Event::Internal(InternalEvent::FunctionBegin(_)) => { self.current_block = 0; - }, + } Event::Wasm(&ref op) | Event::WasmOwned(ref op) => { self.current_block += 1; match *op { Operator::Loop { .. } - | Operator::Block { .. } - | Operator::End - | Operator::If { .. } - | Operator::Else - | Operator::Unreachable - | Operator::Br { .. } - | Operator::BrTable { .. } - | Operator::BrIf { .. } - | Operator::Call { .. } - | Operator::CallIndirect { .. } - => { - sink.push(Event::Internal(InternalEvent::GetInternal(0))); - sink.push(Event::WasmOwned(Operator::I64Const { value: self.current_block as i64 })); - sink.push(Event::WasmOwned(Operator::I64Add)); - sink.push(Event::Internal(InternalEvent::SetInternal(0))); - self.current_block = 0; - }, + | Operator::Block { .. } + | Operator::End + | Operator::If { .. } + | Operator::Else + | Operator::Unreachable + | Operator::Br { .. } + | Operator::BrTable { .. } + | Operator::BrIf { .. } + | Operator::Call { .. } + | Operator::CallIndirect { .. } => { + sink.push(Event::Internal(InternalEvent::GetInternal(0))); + sink.push(Event::WasmOwned(Operator::I64Const { + value: self.current_block as i64, + })); + sink.push(Event::WasmOwned(Operator::I64Add)); + sink.push(Event::Internal(InternalEvent::SetInternal(0))); + self.current_block = 0; + } _ => {} } match *op { - Operator::Br { .. } - | Operator::BrTable { .. } - | Operator::BrIf { .. } - | Operator::Call { .. } - | Operator::CallIndirect { .. } - => { - sink.push(Event::Internal(InternalEvent::GetInternal(0))); - sink.push(Event::WasmOwned(Operator::I64Const { value: self.limit as i64 })); - sink.push(Event::WasmOwned(Operator::I64GeU)); - sink.push(Event::WasmOwned(Operator::If { ty: WpType::EmptyBlockType })); - sink.push(Event::Internal(InternalEvent::Breakpoint(Box::new(move |ctx| { + Operator::Br { .. } + | Operator::BrTable { .. } + | Operator::BrIf { .. } + | Operator::Call { .. } + | Operator::CallIndirect { .. } => { + sink.push(Event::Internal(InternalEvent::GetInternal(0))); + sink.push(Event::WasmOwned(Operator::I64Const { + value: self.limit as i64, + })); + sink.push(Event::WasmOwned(Operator::I64GeU)); + sink.push(Event::WasmOwned(Operator::If { + ty: WpType::EmptyBlockType, + })); + sink.push(Event::Internal(InternalEvent::Breakpoint(Box::new( + move |ctx| { eprintln!("execution limit reached"); unsafe { (ctx.throw)(); } - })))); - sink.push(Event::WasmOwned(Operator::End)); - }, + }, + )))); + sink.push(Event::WasmOwned(Operator::End)); + } _ => {} } - }, + } _ => {} } sink.push(op); diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 52aec386eaa..cef525f2c91 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -15,10 +15,7 @@ use crate::{ }, vm, }; -use std::{ - slice, - fmt::Debug, -}; +use std::{fmt::Debug, slice}; pub const INTERNALS_SIZE: usize = 256; diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index 9ae20d8c942..f7a997e2999 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -41,7 +41,7 @@ impl fmt::Debug for InternalEvent { } pub struct BkptInfo { - pub throw: unsafe extern "C" fn () -> !, + pub throw: unsafe extern "C" fn() -> !, } pub trait ModuleCodeGenerator, RM: RunnableModule, E: Debug> { diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index 4a0c3e4f5f1..6b8ea5569a5 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -1494,7 +1494,6 @@ impl FunctionCodeGenerator for X64FunctionCode { let a = self.assembler.as_mut().unwrap(); - let op = match ev { Event::Wasm(x) => x, Event::WasmOwned(ref x) => x, diff --git a/lib/singlepass-backend/src/protect_unix.rs b/lib/singlepass-backend/src/protect_unix.rs index e26467b8e05..56ac61519c5 100644 --- a/lib/singlepass-backend/src/protect_unix.rs +++ b/lib/singlepass-backend/src/protect_unix.rs @@ -35,9 +35,7 @@ extern "C" fn signal_trap_handler( let bkpt_map = BKPT_MAP.with(|x| x.borrow().last().map(|x| x.clone())); if let Some(bkpt_map) = bkpt_map { if let Some(ref x) = bkpt_map.get(&(ip as usize)) { - (x)(BkptInfo { - throw: throw, - }); + (x)(BkptInfo { throw: throw }); return; } } diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 8231c60b410..806af915879 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -17,18 +17,22 @@ use wasmer::*; use wasmer_clif_backend::CraneliftCompiler; #[cfg(feature = "backend:llvm")] use wasmer_llvm_backend::LLVMCompiler; +#[cfg(feature = "backend:singlepass")] +use wasmer_middleware_common::metering::Metering; use wasmer_runtime::{ cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH}, error::RuntimeError, Func, Value, }; +#[cfg(feature = "backend:singlepass")] +use wasmer_runtime_core::codegen::{MiddlewareChain, StreamingCompiler}; use wasmer_runtime_core::{ self, backend::{Compiler, CompilerConfig, MemoryBoundCheckMode}, loader::{Instance as LoadedInstance, LocalLoader}, }; #[cfg(feature = "backend:singlepass")] -use wasmer_singlepass_backend::SinglePassCompiler; +use wasmer_singlepass_backend::ModuleCodeGenerator as SinglePassMCG; #[cfg(feature = "wasi")] use wasmer_wasi; @@ -110,6 +114,9 @@ struct Run { /// Application arguments #[structopt(name = "--", raw(multiple = "true"))] args: Vec, + + #[structopt(long = "inst-limit")] + instruction_limit: Option, } #[allow(dead_code)] @@ -286,7 +293,16 @@ fn execute_wasm(options: &Run) -> Result<(), String> { let compiler: Box = match options.backend { #[cfg(feature = "backend:singlepass")] - Backend::Singlepass => Box::new(SinglePassCompiler::new()), + Backend::Singlepass => { + let c: StreamingCompiler = StreamingCompiler::new(|| { + let mut chain = MiddlewareChain::new(); + if let Some(limit) = options.instruction_limit { + chain.push(Metering::new(limit)); + } + chain + }); + Box::new(c) + } #[cfg(not(feature = "backend:singlepass"))] Backend::Singlepass => return Err("The singlepass backend is not enabled".to_string()), Backend::Cranelift => Box::new(CraneliftCompiler::new()), From b830f10fa07050d20cf8523fff2540c0f8276030 Mon Sep 17 00:00:00 2001 From: losfair Date: Fri, 17 May 2019 01:20:09 +0800 Subject: [PATCH 5/5] Update metering data on return --- lib/middleware-common/src/metering.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/middleware-common/src/metering.rs b/lib/middleware-common/src/metering.rs index 0b95e5f978c..cf82b66d185 100644 --- a/lib/middleware-common/src/metering.rs +++ b/lib/middleware-common/src/metering.rs @@ -43,7 +43,8 @@ impl FunctionMiddleware for Metering { | Operator::BrTable { .. } | Operator::BrIf { .. } | Operator::Call { .. } - | Operator::CallIndirect { .. } => { + | Operator::CallIndirect { .. } + | Operator::Return => { sink.push(Event::Internal(InternalEvent::GetInternal(0))); sink.push(Event::WasmOwned(Operator::I64Const { value: self.current_block as i64,