//! The Wasmi interpreter.

mod block_type;
mod code_map;
mod config;
mod executor;
mod func_types;
mod limits;
mod resumable;
mod translator;
mod utils;

pub(crate) use self::{
    block_type::BlockType,
    executor::{
        Cell,
        InOutParams,
        InOutResults,
        Inst,
        LiftFromCells,
        LiftFromCellsByValue,
        LoadByVal,
        LowerToCells,
        Stack,
    },
    func_types::DedupFuncType,
    translator::{
        FuncTranslationDriver,
        FuncTranslator,
        FuncTranslatorAllocations,
        LazyFuncTranslator,
        ValidatingFuncTranslator,
        WasmTranslator,
        required_cells_for_tys,
    },
};
use self::{
    code_map::{CodeMap, CompiledFuncEntity},
    func_types::FuncTypeRegistry,
    resumable::ResumableCallBase,
};
pub use self::{
    code_map::{EngineFunc, EngineFuncSpan, EngineFuncSpanIter},
    config::{CompilationMode, Config},
    limits::{EnforcedLimits, EnforcedLimitsError, StackConfig},
    resumable::{
        ResumableCall,
        ResumableCallHostTrap,
        ResumableCallOutOfFuel,
        ResumableHostTrapError,
        ResumableOutOfFuelError,
        TypedResumableCall,
        TypedResumableCallHostTrap,
        TypedResumableCallOutOfFuel,
    },
    translator::TranslationError,
};
use crate::{
    Error,
    Func,
    FuncType,
    StoreContextMut,
    module::{FuncIdx, ModuleHeader},
};
use alloc::{
    sync::{Arc, Weak},
    vec::Vec,
};
use core::sync::atomic::{AtomicU32, Ordering};
use spin::{Mutex, RwLock};
use wasmparser::{FuncToValidate, FuncValidatorAllocations, ValidatorResources};

#[cfg(doc)]
use crate::Store;

/// A unique engine index.
///
/// # Note
///
/// Used to protect against invalid entity indices.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct EngineId(u32);

impl EngineId {
    /// Returns a new unique [`EngineId`].
    fn new() -> Self {
        /// A static store index counter.
        static CURRENT_STORE_IDX: AtomicU32 = AtomicU32::new(0);
        let next_idx = CURRENT_STORE_IDX.fetch_add(1, Ordering::AcqRel);
        Self(next_idx)
    }

    /// Wraps a `value` into a [`EngineOwned<T>`] associated to `self`.
    pub fn wrap<T>(self, value: T) -> EngineOwned<T> {
        EngineOwned {
            engine: self,
            value,
        }
    }

    /// Unwraps `owned`'s value if [`EngineOwned<T>`] is associated to `self`.
    ///
    /// Otherwise returns `None`.
    pub fn unwrap<T>(self, owned: EngineOwned<T>) -> Option<T> {
        if self != owned.engine {
            return None;
        }
        Some(owned.value)
    }
}

/// A value associated to a [`Store`].
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct EngineOwned<T> {
    /// The identifier of the associated engine.
    engine: EngineId,
    /// The engine owned value.
    value: T,
}

/// The Wasmi interpreter.
///
/// # Note
///
/// - The current Wasmi engine implements a bytecode interpreter.
/// - This structure is intentionally cheap to copy.
///   Most of its API has a `&self` receiver, so can be shared easily.
#[derive(Debug, Clone)]
pub struct Engine {
    inner: Arc<EngineInner>,
}

/// A weak reference to an [`Engine`].
#[derive(Debug, Clone)]
pub struct EngineWeak {
    inner: Weak<EngineInner>,
}

impl EngineWeak {
    /// Upgrades the [`EngineWeak`] to an [`Engine`].
    ///
    /// Returns `None` if strong references (the [`Engine`] itself) no longer exist.
    pub fn upgrade(&self) -> Option<Engine> {
        let inner = self.inner.upgrade()?;
        Some(Engine { inner })
    }
}

impl Default for Engine {
    fn default() -> Self {
        Self::new(&Config::default())
    }
}

impl Engine {
    /// Creates a new [`Engine`] with default configuration.
    ///
    /// # Note
    ///
    /// Users should use [`Engine::default`] to construct a default [`Engine`].
    pub fn new(config: &Config) -> Self {
        Self {
            inner: Arc::new(EngineInner::new(config)),
        }
    }

    /// Creates an [`EngineWeak`] from the given [`Engine`].
    pub fn weak(&self) -> EngineWeak {
        EngineWeak {
            inner: Arc::downgrade(&self.inner),
        }
    }

    /// Returns a shared reference to the [`Config`] of the [`Engine`].
    pub fn config(&self) -> &Config {
        self.inner.config()
    }

    /// Returns `true` if both [`Engine`] references `a` and `b` refer to the same [`Engine`].
    pub fn same(a: &Engine, b: &Engine) -> bool {
        Arc::ptr_eq(&a.inner, &b.inner)
    }

    /// Allocates a new function type to the [`Engine`].
    pub(super) fn alloc_func_type(&self, func_type: FuncType) -> DedupFuncType {
        self.inner.alloc_func_type(func_type)
    }

    /// Resolves a deduplicated function type into a [`FuncType`] entity.
    ///
    /// # Panics
    ///
    /// - If the deduplicated function type is not owned by the engine.
    /// - If the deduplicated function type cannot be resolved to its entity.
    pub(super) fn resolve_func_type<F, R>(&self, func_type: &DedupFuncType, f: F) -> R
    where
        F: FnOnce(&FuncType) -> R,
    {
        self.inner.resolve_func_type(func_type, f)
    }

    /// Allocates `amount` new uninitialized [`EngineFunc`] to the [`CodeMap`].
    ///
    /// Returns a range of [`EngineFunc`]s to allow accessing the allocated [`EngineFunc`].
    pub(super) fn alloc_funcs(&self, amount: usize) -> EngineFuncSpan {
        self.inner.alloc_funcs(amount)
    }

    /// Translates the Wasm function using the [`Engine`].
    ///
    /// - Uses the internal [`Config`] to drive the function translation as mandated.
    /// - Reuses translation and validation allocations to be more efficient when used for many translation units.
    ///
    /// # Parameters
    ///
    /// - `func_index`: The index of the translated function within its Wasm module.
    /// - `engine_func`: The index of the translated function in the [`Engine`].
    /// - `offset`: The global offset of the Wasm function body within the Wasm binary.
    /// - `bytes`: The bytes that make up the Wasm encoded function body of the translated function.
    /// - `module`: The module header information of the Wasm module of the translated function.
    /// - `func_to_validate`: Optionally validates the translated function.
    ///
    /// # Errors
    ///
    /// - If function translation fails.
    /// - If function validation fails.
    pub(crate) fn translate_func(
        &self,
        func_index: FuncIdx,
        engine_func: EngineFunc,
        offset: usize,
        bytes: &[u8],
        module: ModuleHeader,
        func_to_validate: Option<FuncToValidate<ValidatorResources>>,
    ) -> Result<(), Error> {
        self.inner.translate_func(
            func_index,
            engine_func,
            offset,
            bytes,
            module,
            func_to_validate,
        )
    }

    /// Returns reusable [`FuncTranslatorAllocations`] from the [`Engine`].
    pub(crate) fn get_translation_allocs(&self) -> FuncTranslatorAllocations {
        self.inner.get_translation_allocs()
    }

    /// Returns reusable [`FuncTranslatorAllocations`] and [`FuncValidatorAllocations`] from the [`Engine`].
    pub(crate) fn get_allocs(&self) -> (FuncTranslatorAllocations, FuncValidatorAllocations) {
        self.inner.get_allocs()
    }

    /// Recycles the given [`FuncTranslatorAllocations`] in the [`Engine`].
    pub(crate) fn recycle_translation_allocs(&self, allocs: FuncTranslatorAllocations) {
        self.inner.recycle_translation_allocs(allocs)
    }

    /// Recycles the given [`FuncTranslatorAllocations`] and [`FuncValidatorAllocations`] in the [`Engine`].
    pub(crate) fn recycle_allocs(
        &self,
        translation: FuncTranslatorAllocations,
        validation: FuncValidatorAllocations,
    ) {
        self.inner.recycle_allocs(translation, validation)
    }

    /// Initializes the uninitialized [`EngineFunc`] for the [`Engine`].
    ///
    /// # Note
    ///
    /// The initialized function will not be compiled after this call and instead
    /// be prepared to be compiled on the fly when it is called the first time.
    ///
    /// # Panics
    ///
    /// - If `func` is an invalid [`EngineFunc`] reference for this [`CodeMap`].
    /// - If `func` refers to an already initialized [`EngineFunc`].
    fn init_lazy_func(
        &self,
        func_idx: FuncIdx,
        func: EngineFunc,
        bytes: &[u8],
        module: &ModuleHeader,
        func_to_validate: Option<FuncToValidate<ValidatorResources>>,
    ) {
        self.inner
            .init_lazy_func(func_idx, func, bytes, module, func_to_validate)
    }

    /// Executes the given [`Func`] with parameters `params`.
    ///
    /// Stores the execution result into `results` upon a successful execution.
    ///
    /// # Note
    ///
    /// - Assumes that the `params` and `results` are well typed.
    ///   Type checks are done at the [`Func::call`] API or when creating
    ///   a new [`TypedFunc`] instance via [`Func::typed`].
    /// - The `params` out parameter is in a valid but unspecified state if this
    ///   function returns with an error.
    ///
    /// # Errors
    ///
    /// - If `params` are overflowing or underflowing the expected amount of parameters.
    /// - If the given `results` do not match the length of the expected results of `func`.
    /// - When encountering a Wasm or host trap during the execution of `func`.
    ///
    /// [`TypedFunc`]: [`crate::TypedFunc`]
    #[inline]
    pub(crate) fn execute_func<T, Params, Results>(
        &self,
        ctx: StoreContextMut<T>,
        func: &Func,
        params: Params,
        results: Results,
    ) -> Result<Results::Value, Error>
    where
        Params: LowerToCells,
        Results: LiftFromCells,
    {
        self.inner.execute_func(ctx, func, params, results)
    }

    /// Executes the given [`Func`] resumably with parameters `params` and returns.
    ///
    /// Stores the execution result into `results` upon a successful execution.
    /// If the execution encounters a host trap it will return a handle to the user
    /// that allows to resume the execution at that point.
    ///
    /// # Note
    ///
    /// - Assumes that the `params` and `results` are well typed.
    ///   Type checks are done at the [`Func::call`] API or when creating
    ///   a new [`TypedFunc`] instance via [`Func::typed`].
    /// - The `params` out parameter is in a valid but unspecified state if this
    ///   function returns with an error.
    ///
    /// # Errors
    ///
    /// - If `params` are overflowing or underflowing the expected amount of parameters.
    /// - If the given `results` do not match the length of the expected results of `func`.
    /// - When encountering a Wasm trap during the execution of `func`.
    /// - When `func` is a host function that traps.
    ///
    /// [`TypedFunc`]: [`crate::TypedFunc`]
    #[inline]
    pub(crate) fn execute_func_resumable<T, Params, Results>(
        &self,
        ctx: StoreContextMut<T>,
        func: &Func,
        params: Params,
        results: Results,
    ) -> Result<ResumableCallBase<Results::Value>, Error>
    where
        Params: LowerToCells,
        Results: LiftFromCells,
    {
        self.inner
            .execute_func_resumable(ctx, func, params, results)
    }

    /// Resumes the given `invocation` after a host trap given the `params`.
    ///
    /// Stores the execution result into `results` upon a successful execution.
    /// If the execution encounters a host trap it will return a handle to the user
    /// that allows to resume the execution at that point.
    ///
    /// # Note
    ///
    /// - Assumes that the `params` and `results` are well typed.
    ///   Type checks are done at the [`Func::call`] API or when creating
    ///   a new [`TypedFunc`] instance via [`Func::typed`].
    /// - The `params` out parameter is in a valid but unspecified state if this
    ///   function returns with an error.
    ///
    /// # Errors
    ///
    /// - If `params` are overflowing or underflowing the expected amount of parameters.
    /// - If the given `results` do not match the length of the expected results of `func`.
    /// - When encountering a Wasm trap during the execution of `func`.
    /// - When `func` is a host function that traps.
    ///
    /// [`TypedFunc`]: [`crate::TypedFunc`]
    #[inline]
    pub(crate) fn resume_func_host_trap<T, Params, Results>(
        &self,
        ctx: StoreContextMut<T>,
        invocation: ResumableCallHostTrap,
        params: Params,
        results: Results,
    ) -> Result<ResumableCallBase<Results::Value>, Error>
    where
        Params: LowerToCells,
        Results: LiftFromCells,
    {
        self.inner
            .resume_func_host_trap(ctx, invocation, params, results)
    }

    /// Resumes the given `invocation` after running out of fuel given the `params`.
    ///
    /// Stores the execution result into `results` upon a successful execution.
    /// If the execution encounters a host trap it will return a handle to the user
    /// that allows to resume the execution at that point.
    ///
    /// # Note
    ///
    /// - Assumes that the `params` and `results` are well typed.
    ///   Type checks are done at the [`Func::call`] API or when creating
    ///   a new [`TypedFunc`] instance via [`Func::typed`].
    /// - The `params` out parameter is in a valid but unspecified state if this
    ///   function returns with an error.
    ///
    /// # Errors
    ///
    /// - If `params` are overflowing or underflowing the expected amount of parameters.
    /// - If the given `results` do not match the length of the expected results of `func`.
    /// - When encountering a Wasm trap during the execution of `func`.
    /// - When `func` is a host function that traps.
    ///
    /// [`TypedFunc`]: [`crate::TypedFunc`]
    #[inline]
    pub(crate) fn resume_func_out_of_fuel<T, Results>(
        &self,
        ctx: StoreContextMut<T>,
        invocation: ResumableCallOutOfFuel,
        results: Results,
    ) -> Result<ResumableCallBase<Results::Value>, Error>
    where
        Results: LiftFromCells,
    {
        self.inner.resume_func_out_of_fuel(ctx, invocation, results)
    }

    /// Recycles the given [`Stack`] for reuse in the [`Engine`].
    pub(crate) fn recycle_stack(&self, stack: Stack) {
        self.inner.recycle_stack(stack)
    }
}

/// The internal state of the Wasmi [`Engine`].
#[derive(Debug)]
pub struct EngineInner {
    /// The [`Config`] of the engine.
    config: Config,
    /// Stores information about all compiled functions.
    code_map: CodeMap,
    /// Deduplicated function types.
    ///
    /// # Note
    ///
    /// The engine deduplicates function types to make the equality
    /// comparison very fast. This helps to speed up indirect calls.
    func_types: RwLock<FuncTypeRegistry>,
    /// Reusable allocation stacks.
    allocs: Mutex<ReusableAllocationStack>,
    /// Reusable engine stacks for Wasm execution.
    ///
    /// Concurrently executing Wasm executions each require their own stack to
    /// operate on. Therefore a Wasm engine is required to provide stacks and
    /// ideally recycles old ones since creation of a new stack is rather expensive.
    stacks: Mutex<EngineStacks>,
}

/// Stacks to hold and distribute reusable allocations.
pub struct ReusableAllocationStack {
    /// The maximum height of each of the allocations stacks.
    max_height: usize,
    /// Allocations required by Wasm function translators.
    translation: Vec<FuncTranslatorAllocations>,
    /// Allocations required by Wasm function validators.
    validation: Vec<FuncValidatorAllocations>,
}

impl Default for ReusableAllocationStack {
    fn default() -> Self {
        Self {
            max_height: 1,
            translation: Vec::new(),
            validation: Vec::new(),
        }
    }
}

impl core::fmt::Debug for ReusableAllocationStack {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        f.debug_struct("ReusableAllocationStack")
            .field("translation", &self.translation)
            // Note: FuncValidatorAllocations is missing Debug impl at the time of writing this commit.
            //       We should derive Debug as soon as FuncValidatorAllocations has a Debug impl in future
            //       wasmparser versions.
            .field("validation", &self.validation.len())
            .finish()
    }
}

impl ReusableAllocationStack {
    /// Returns reusable [`FuncTranslatorAllocations`] from the [`Engine`].
    pub fn get_translation_allocs(&mut self) -> FuncTranslatorAllocations {
        self.translation.pop().unwrap_or_default()
    }

    /// Returns reusable [`FuncValidatorAllocations`] from the [`Engine`].
    pub fn get_validation_allocs(&mut self) -> FuncValidatorAllocations {
        self.validation.pop().unwrap_or_default()
    }

    /// Recycles the given [`FuncTranslatorAllocations`] in the [`Engine`].
    pub fn recycle_translation_allocs(&mut self, recycled: FuncTranslatorAllocations) {
        debug_assert!(self.translation.len() <= self.max_height);
        if self.translation.len() >= self.max_height {
            return;
        }
        self.translation.push(recycled);
    }

    /// Recycles the given [`FuncValidatorAllocations`] in the [`Engine`].
    pub fn recycle_validation_allocs(&mut self, recycled: FuncValidatorAllocations) {
        debug_assert!(self.validation.len() <= self.max_height);
        if self.validation.len() >= self.max_height {
            return;
        }
        self.validation.push(recycled);
    }
}

/// The engine's stacks for reuse.
///
/// Required for efficient concurrent Wasm executions.
#[derive(Debug)]
pub struct EngineStacks {
    /// Stacks to be (re)used.
    stacks: Vec<Stack>,
    /// The stack configuration.
    config: StackConfig,
}

// # Safety
//
// The `EngineStacks` type does not automatically implement `Send` because
// its internal `Stack` type used in `Vec<Stack>` does not implement `Send`.
// The reason is that for execution performance reasons `Stack` uses raw pointers
// internally.
// However, those raw pointers never leak outside and are only point to memory
// areas heap allocated for the `Stack`. The `Stack` itself is used via `Vec`
// and no accesses to it are always going through a `&mut Store`.
//
// In summary it is safe to impl `Send` for the outer `EngineStack` since we
// make sure not to break safety invariants that make `Stack` itself not `Send`.
unsafe impl Send for EngineStacks {}

// # Safety
//
// The `EngineStacks` type does not automatically implement `Sync` because
// its internal `Stack` type used in `Vec<Stack>` does not implement `Sync`.
// The reason is that for execution performance reasons `Stack` uses raw pointers
// internally.
// However, those raw pointers never leak outside and are only point to memory
// areas heap allocated for the `Stack`. The `Stack` itself is used via `Vec`
// and no accesses to it are always going through a `&mut Store`.
//
// In summary it is safe to impl `Sync` for the outer `EngineStack` since we
// make sure not to break safety invariants that make `Stack` itself not `Sync`.
unsafe impl Sync for EngineStacks {}

impl EngineStacks {
    /// Creates new [`EngineStacks`] with the given [`StackConfig`].
    pub fn new(config: &StackConfig) -> Self {
        Self {
            stacks: Vec::new(),
            config: *config,
        }
    }

    /// Reuse or create a new [`Stack`] if none was available.
    pub fn reuse_or_new(&mut self) -> Stack {
        match self.stacks.pop() {
            Some(stack) => stack,
            None => Stack::new(&self.config),
        }
    }

    /// Disose and recycle the `stack`.
    pub fn recycle(&mut self, stack: Stack) {
        if stack.bytes_allocated() > 0 && self.stacks.len() < self.config.max_cached_stacks() {
            self.stacks.push(stack);
        }
    }
}

impl EngineInner {
    /// Creates a new [`EngineInner`] with the given [`Config`].
    fn new(config: &Config) -> Self {
        let engine_idx = EngineId::new();
        Self {
            config: config.clone(),
            code_map: CodeMap::new(config),
            func_types: RwLock::new(FuncTypeRegistry::new(engine_idx)),
            allocs: Mutex::new(ReusableAllocationStack::default()),
            stacks: Mutex::new(EngineStacks::new(&config.stack)),
        }
    }

    /// Returns a shared reference to the [`Config`] of the [`EngineInner`].
    fn config(&self) -> &Config {
        &self.config
    }

    /// Allocates a new function type to the [`EngineInner`].
    fn alloc_func_type(&self, func_type: FuncType) -> DedupFuncType {
        self.func_types.write().alloc_func_type(func_type)
    }

    /// Resolves a deduplicated function type into a [`FuncType`] entity.
    ///
    /// # Panics
    ///
    /// - If the deduplicated function type is not owned by the engine.
    /// - If the deduplicated function type cannot be resolved to its entity.
    fn resolve_func_type<F, R>(&self, func_type: &DedupFuncType, f: F) -> R
    where
        F: FnOnce(&FuncType) -> R,
    {
        f(self.func_types.read().resolve_func_type(func_type))
    }

    /// Allocates `amount` new uninitialized [`EngineFunc`] to the [`CodeMap`].
    ///
    /// Returns a range of [`EngineFunc`]s to allow accessing the allocated [`EngineFunc`].
    fn alloc_funcs(&self, amount: usize) -> EngineFuncSpan {
        self.code_map.alloc_funcs(amount)
    }

    /// Translates the Wasm function using the [`Engine`].
    ///
    /// For more information read [`Engine::translate_func`].
    fn translate_func(
        &self,
        func_index: FuncIdx,
        engine_func: EngineFunc,
        offset: usize,
        bytes: &[u8],
        module: ModuleHeader,
        func_to_validate: Option<FuncToValidate<ValidatorResources>>,
    ) -> Result<(), Error> {
        let features = self.config().wasm_features();
        match (self.config.get_compilation_mode(), func_to_validate) {
            (CompilationMode::Eager, Some(func_to_validate)) => {
                let (translation_allocs, validation_allocs) = self.get_allocs();
                let validator = func_to_validate.into_validator(validation_allocs);
                let translator = FuncTranslator::new(func_index, module, translation_allocs)?;
                let translator = ValidatingFuncTranslator::new(validator, translator)?;
                let allocs = FuncTranslationDriver::new(offset, bytes, translator)?
                    .translate(|func_entity| self.init_func(engine_func, func_entity))?;
                self.recycle_allocs(allocs.translation, allocs.validation);
            }
            (CompilationMode::Eager, None) => {
                let allocs = self.get_translation_allocs();
                let translator = FuncTranslator::new(func_index, module, allocs)?;
                let allocs = FuncTranslationDriver::new(offset, bytes, translator)?
                    .translate(|func_entity| self.init_func(engine_func, func_entity))?;
                self.recycle_translation_allocs(allocs);
            }
            (CompilationMode::LazyTranslation, Some(func_to_validate)) => {
                let allocs = self.get_validation_allocs();
                let translator =
                    LazyFuncTranslator::new_unchecked(func_index, engine_func, module, features);
                let validator = func_to_validate.into_validator(allocs);
                let translator = ValidatingFuncTranslator::new(validator, translator)?;
                let allocs = FuncTranslationDriver::new(offset, bytes, translator)?
                    .translate(|func_entity| self.init_func(engine_func, func_entity))?;
                self.recycle_validation_allocs(allocs.validation);
            }
            (CompilationMode::Lazy | CompilationMode::LazyTranslation, func_to_validate) => {
                let translator = match func_to_validate {
                    Some(func_to_validate) => {
                        LazyFuncTranslator::new(func_index, engine_func, module, func_to_validate)
                    }
                    None => {
                        LazyFuncTranslator::new_unchecked(func_index, engine_func, module, features)
                    }
                };
                FuncTranslationDriver::new(offset, bytes, translator)?
                    .translate(|func_entity| self.init_func(engine_func, func_entity))?;
            }
        }
        Ok(())
    }

    /// Returns reusable [`FuncTranslatorAllocations`] from the [`Engine`].
    fn get_translation_allocs(&self) -> FuncTranslatorAllocations {
        self.allocs.lock().get_translation_allocs()
    }

    /// Returns reusable [`FuncValidatorAllocations`] from the [`Engine`].
    fn get_validation_allocs(&self) -> FuncValidatorAllocations {
        self.allocs.lock().get_validation_allocs()
    }

    /// Returns reusable [`FuncTranslatorAllocations`] and [`FuncValidatorAllocations`] from the [`Engine`].
    ///
    /// # Note
    ///
    /// This method is a bit more efficient than calling both
    /// - [`EngineInner::get_translation_allocs`]
    /// - [`EngineInner::get_validation_allocs`]
    fn get_allocs(&self) -> (FuncTranslatorAllocations, FuncValidatorAllocations) {
        let mut allocs = self.allocs.lock();
        let translation = allocs.get_translation_allocs();
        let validation = allocs.get_validation_allocs();
        (translation, validation)
    }

    /// Recycles the given [`FuncTranslatorAllocations`] in the [`Engine`].
    fn recycle_translation_allocs(&self, allocs: FuncTranslatorAllocations) {
        self.allocs.lock().recycle_translation_allocs(allocs)
    }

    /// Recycles the given [`FuncValidatorAllocations`] in the [`Engine`].
    fn recycle_validation_allocs(&self, allocs: FuncValidatorAllocations) {
        self.allocs.lock().recycle_validation_allocs(allocs)
    }

    /// Recycles the given [`FuncTranslatorAllocations`] and [`FuncValidatorAllocations`] in the [`Engine`].
    ///
    /// # Note
    ///
    /// This method is a bit more efficient than calling both
    /// - [`EngineInner::recycle_translation_allocs`]
    /// - [`EngineInner::recycle_validation_allocs`]
    fn recycle_allocs(
        &self,
        translation: FuncTranslatorAllocations,
        validation: FuncValidatorAllocations,
    ) {
        let mut allocs = self.allocs.lock();
        allocs.recycle_translation_allocs(translation);
        allocs.recycle_validation_allocs(validation);
    }

    /// Initializes the uninitialized [`EngineFunc`] for the [`EngineInner`].
    ///
    /// # Note
    ///
    /// The initialized function will be compiled and ready to be executed after this call.
    ///
    /// # Panics
    ///
    /// - If `func` is an invalid [`EngineFunc`] reference for this [`CodeMap`].
    /// - If `func` refers to an already initialized [`EngineFunc`].
    fn init_func(&self, engine_func: EngineFunc, func_entity: CompiledFuncEntity) {
        self.code_map
            .init_func_as_compiled(engine_func, func_entity)
    }

    /// Initializes the uninitialized [`EngineFunc`] for the [`Engine`].
    ///
    /// # Note
    ///
    /// The initialized function will not be compiled after this call and instead
    /// be prepared to be compiled on the fly when it is called the first time.
    ///
    /// # Panics
    ///
    /// - If `func` is an invalid [`EngineFunc`] reference for this [`CodeMap`].
    /// - If `func` refers to an already initialized [`EngineFunc`].
    fn init_lazy_func(
        &self,
        func_idx: FuncIdx,
        func: EngineFunc,
        bytes: &[u8],
        module: &ModuleHeader,
        func_to_validate: Option<FuncToValidate<ValidatorResources>>,
    ) {
        self.code_map
            .init_func_as_uncompiled(func, func_idx, bytes, module, func_to_validate)
    }

    /// Recycles the given [`Stack`].
    fn recycle_stack(&self, stack: Stack) {
        self.stacks.lock().recycle(stack)
    }
}

Homonyms

cyberia/src/components/mod.rs
cyberia/src/pages/mod.rs
cyb/optica/src/output/mod.rs
neural/trident/src/compile/mod.rs
cyb/optica/src/parser/mod.rs
soft3/nox/rs/data/mod.rs
neural/trident/src/api/mod.rs
soft3/mir/src/graph/mod.rs
cyb/optica/src/render/mod.rs
cyb/optica/src/scanner/mod.rs
soft3/cybergraph/tests/common/mod.rs
neural/trident/src/verify/mod.rs
soft3/tru/rs/model/mod.rs
neural/trident/src/diagnostic/mod.rs
soft3/mudra/src/proof/mod.rs
cyb/optica/src/graph/mod.rs
soft3/glia/import/loader/mod.rs
soft3/glia/run/backend/mod.rs
neural/trident/src/import/mod.rs
soft3/tru/rs/pass/mod.rs
soft3/mir/src/bevy/mod.rs
neural/trident/src/package/mod.rs
neural/trident/src/lsp/mod.rs
neural/trident/src/field/mod.rs
cyb/prysm/atoms/rs/mod.rs
soft3/tru/rs/graph/mod.rs
neural/trident/src/deploy/mod.rs
soft3/mir/src/epoch/mod.rs
neural/trident/src/runtime/mod.rs
soft3/glia/run/arch/mod.rs
neural/trident/src/typecheck/mod.rs
neural/trident/src/gpu/mod.rs
soft3/nox/rs/jets/mod.rs
soft3/glia/run/tokenizer/mod.rs
soft3/mir/src/frame/mod.rs
neural/trident/src/ir/mod.rs
neural/trident/src/config/mod.rs
soft3/nox/rs/patterns/mod.rs
neural/trident/src/cost/mod.rs
soft3/glia/run/ir/mod.rs
neural/trident/src/cli/mod.rs
soft3/tru/rs/focusing/mod.rs
neural/trident/src/neural/mod.rs
cyb/optica/src/query/mod.rs
cyb/prysm/system/rs/mod.rs
neural/trident/src/ast/mod.rs
soft3/glia/run/bench/mod.rs
cyb/prysm/molecules/rs/mod.rs
cyb/optica/src/server/mod.rs
soft3/glia/run/core/mod.rs
neural/trident/src/syntax/mod.rs
cyb/honeycrisp/acpu/src/vector/mod.rs
soft3/glia/run/backend/cpu/mod.rs
soft3/zheng/rs/src/spartan/mod.rs
soft3/bbg/rs/src/storage/mod.rs
neural/trident/src/config/resolve/mod.rs
cyb/honeycrisp/aruminium/src/ffi/mod.rs
cyb/cyb/cyb-shell/src/worlds/mod.rs
cyb/wysm/crates/wasi/tests/mod.rs
soft3/zheng/rs/src/ccs/mod.rs
neural/trident/src/package/store/mod.rs
cyb/cyb/cyb-shell/src/shell/mod.rs
cyb/wysm/crates/wasmi/tests/mod.rs
neural/trident/src/verify/synthesize/mod.rs
cyb/honeycrisp/acpu/src/field/mod.rs
neural/rs/macros/src/addressed/mod.rs
soft3/glia/run/cli/cmd/mod.rs
neural/trident/src/cost/stack_verifier/mod.rs
neural/eidos/rs/src/stdlib/mod.rs
neural/trident/src/verify/sym/mod.rs
neural/trident/src/syntax/format/mod.rs
neural/trident/src/syntax/grammar/mod.rs
neural/trident/src/lsp/util/mod.rs
neural/rs/rsc/src/lints/mod.rs
neural/trident/src/typecheck/tests/mod.rs
neural/eidos/rs/src/surface/mod.rs
soft3/mir/src/frame/tiers/mod.rs
cyb/honeycrisp/acpu/src/pulse/mod.rs
neural/trident/src/ir/lir/mod.rs
neural/trident/src/package/registry/mod.rs
neural/trident/src/neural/model/mod.rs
neural/trident/src/package/hash/mod.rs
cyb/honeycrisp/acpu/src/sync/mod.rs
soft3/glia/run/arch/decoder/mod.rs
neural/trident/src/verify/report/mod.rs
neural/trident/src/ir/tir/mod.rs
cyb/honeycrisp/rane/src/mil/mod.rs
cyb/honeycrisp/acpu/src/crypto/mod.rs
soft3/zheng/rs/src/folding/mod.rs
neural/trident/src/ir/tree/mod.rs
cyb/honeycrisp/acpu/src/matrix/mod.rs
soft3/glia/run/backend/honeycrisp/mod.rs
neural/eidos/rs/src/elab/mod.rs
neural/rs/macros/src/registers/mod.rs
neural/trident/src/verify/solve/mod.rs
neural/rs/core/src/fixed_point/mod.rs
neural/trident/src/syntax/parser/mod.rs
neural/trident/src/neural/data/mod.rs
neural/trident/src/verify/smt/mod.rs
soft3/radio/iroh-blobs/examples/common/mod.rs
soft3/strata/nebu/rs/extension/mod.rs
neural/rs/darwin-sys/src/ffi/mod.rs
cyb/honeycrisp/acpu/src/sparse/mod.rs
soft3/glia/run/backend/wgpu/mod.rs
neural/rs/core/src/bounded/mod.rs
neural/eidos/rs/src/tactic_ext/mod.rs
neural/trident/src/cost/model/mod.rs
cyb/wysm/crates/wast/tests/mod.rs
soft3/radio/iroh-blobs/src/store/mod.rs
neural/trident/src/package/manifest/mod.rs
cyb/cyb/cyb-shell/src/agent/mod.rs
neural/trident/src/neural/training/mod.rs
neural/trident/src/verify/equiv/mod.rs
neural/trident/src/syntax/lexer/mod.rs
cyb/honeycrisp/acpu/src/numeric/mod.rs
soft3/radio/cyber-bao/src/io/mod.rs
neural/trident/src/ir/kir/mod.rs
cyb/honeycrisp/aruminium/src/render/mod.rs
neural/trident/src/neural/inference/mod.rs
cyb/honeycrisp/acpu/src/probe/mod.rs
neural/trident/src/api/tests/mod.rs
cyb/honeycrisp/acpu/src/gemm/mod.rs
soft3/nox/rs/jets/backends/mod.rs
neural/trident/src/lsp/semantic/mod.rs
neural/rs/macros/src/cell/mod.rs
neural/trident/src/config/scaffold/mod.rs
soft3/zheng/rs/src/sumcheck/mod.rs
cyb/evy/forks/bevy_ecs/src/entity/mod.rs
neural/trident/src/ir/tir/builder/mod.rs
cyb/evy/forks/bevy_ecs/src/system/mod.rs
cyb/evy/forks/bevy_sprite_render/src/render/mod.rs
soft3/strata/jali/wgsl/src/shaders/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/tonemapping/mod.rs
cyb/evy/forks/bevy_anti_alias/src/dlss/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/skybox/mod.rs
cyb/evy/forks/bevy_sprite_render/src/text2d/mod.rs
cyb/evy/forks/bevy_render/src/batching/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/experimental/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/oit/mod.rs
cyb/evy/forks/bevy_sprite_render/src/tilemap_chunk/mod.rs
cyb/evy/forks/bevy_pbr/src/atmosphere/mod.rs
cyb/evy/forks/bevy_post_process/src/motion_blur/mod.rs
cyb/wysm/crates/wasmi/src/store/mod.rs
cyb/evy/forks/bevy_render/src/render_graph/mod.rs
cyb/wysm/crates/wasmi/benches/bench/mod.rs
cyb/evy/forks/bevy_anti_alias/src/contrast_adaptive_sharpening/mod.rs
neural/trident/src/ir/tir/stack/mod.rs
cyb/evy/forks/bevy_render/src/texture/mod.rs
cyb/wysm/crates/c_api/src/types/mod.rs
soft3/strata/genies/wgsl/src/shaders/mod.rs
cyb/wysm/crates/core/src/memory/mod.rs
bootloader/go-cyber/mcp/rust/src/proto/mod.rs
cyb/evy/forks/bevy_ecs/src/bundle/mod.rs
cyb/evy/forks/bevy_mesh/src/primitives/mod.rs
cyb/evy/forks/bevy_ecs/src/schedule/mod.rs
cyb/wysm/crates/wasmi/src/module/mod.rs
cyb/evy/forks/bevy_sprite/src/texture_slice/mod.rs
cyb/evy/forks/bevy_ecs/src/observer/mod.rs
neural/trident/src/ir/tir/neural/mod.rs
cyb/evy/forks/bevy_render/src/view/mod.rs
neural/trident/src/ir/lir/lower/mod.rs
cyb/evy/forks/bevy_anti_alias/src/smaa/mod.rs
bootloader/go-cyber/mcp/rust/src/clients/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/fullscreen_vertex_shader/mod.rs
cyb/wysm/crates/wasmi/tests/integration/mod.rs
cyb/wysm/crates/ir/src/decode/mod.rs
cyb/wysm/crates/wasmi/src/memory/mod.rs
cyb/evy/crates/evy_prysm_core/src/layout/mod.rs
cyb/evy/forks/bevy_anti_alias/src/fxaa/mod.rs
cyb/evy/forks/bevy_pbr/src/prepass/mod.rs
cyb/evy/forks/bevy_render/src/render_resource/mod.rs
cyb/evy/forks/bevy_ecs/src/query/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/core_2d/mod.rs
cyb/wysm/crates/cli/src/commands/mod.rs
cyb/evy/forks/bevy_render/src/renderer/mod.rs
cyb/wysm/crates/collections/src/arena/mod.rs
cyb/evy/forks/bevy_post_process/src/effect_stack/mod.rs
cyb/evy/forks/bevy_ecs/src/change_detection/mod.rs
cyb/evy/forks/bevy_pbr/src/ssao/mod.rs
cyb/evy/forks/naga/src/keywords/mod.rs
cyb/evy/forks/naga/src/compact/mod.rs
neural/trident/src/ir/tir/lower/mod.rs
cyb/evy/forks/bevy_pbr/src/render/mod.rs
cyb/evy/forks/bevy_ecs/src/world/mod.rs
cyb/evy/forks/bevy_anti_alias/src/taa/mod.rs
cyb/evy/forks/bevy_ecs/src/reflect/mod.rs
soft3/strata/kuro/wgsl/src/shaders/mod.rs
cyb/evy/forks/bevy_ecs/src/error/mod.rs
neural/trident/src/ir/kir/lower/mod.rs
cyb/evy/forks/naga/src/proc/mod.rs
cyb/evy/forks/bevy_ecs/src/event/mod.rs
cyb/evy/forks/bevy_ecs/src/component/mod.rs
cyb/evy/forks/bevy_sprite_render/src/mesh2d/mod.rs
cyb/evy/forks/bevy_ecs/src/relationship/mod.rs
cyb/wysm/crates/wasmi/src/instance/mod.rs
cyb/evy/forks/bevy_pbr/src/ssr/mod.rs
bootloader/go-cyber/mcp/rust/src/tools/mod.rs
soft3/glia/run/backend/honeycrisp/kernels/mod.rs
cyb/evy/forks/naga/src/back/mod.rs
soft3/glia/run/backend/cpu/quant/mod.rs
cyb/wysm/crates/core/src/table/mod.rs
cyb/evy/forks/bevy_post_process/src/dof/mod.rs
cyb/evy/forks/bevy_pbr/src/light_probe/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/prepass/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/upscaling/mod.rs
cyb/wysm/crates/wasmi/src/table/mod.rs
cyb/evy/forks/bevy_post_process/src/bloom/mod.rs
cyb/evy/forks/bevy_pbr/src/lightmap/mod.rs
neural/trident/src/ir/tir/optimize/mod.rs
cyb/evy/forks/bevy_gizmos/src/primitives/mod.rs
cyb/evy/forks/bevy_post_process/src/auto_exposure/mod.rs
neural/trident/src/neural/data/tir_graph/mod.rs
cyb/evy/forks/bevy_render/src/experimental/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/deferred/mod.rs
cyb/evy/forks/naga/src/arena/mod.rs
cyb/evy/forks/bevy_render/src/diagnostic/mod.rs
cyb/evy/forks/bevy_render/src/render_phase/mod.rs
cyb/evy/forks/bevy_transform/src/components/mod.rs
soft3/strata/trop/wgsl/src/shaders/mod.rs
soft3/glia/run/backend/wgpu/kernels/mod.rs
cyb/evy/forks/bevy_sprite_render/src/texture_slice/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/core_3d/mod.rs
cyb/evy/forks/bevy_render/src/mesh/mod.rs
neural/trident/src/ir/tree/lower/mod.rs
cyb/evy/forks/bevy_pbr/src/volumetric_fog/mod.rs
cyb/evy/forks/bevy_pbr/src/decal/mod.rs
cyb/wysm/crates/fuzz/src/oracle/mod.rs
cyb/evy/forks/bevy_ecs/src/message/mod.rs
cyb/evy/forks/naga/src/valid/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/blit/mod.rs
cyb/evy/forks/naga/src/front/mod.rs
cyb/wysm/crates/wasi/src/sync/mod.rs
cyb/evy/forks/bevy_pbr/src/meshlet/mod.rs
cyb/evy/forks/bevy_pbr/src/deferred/mod.rs
neural/trident/src/syntax/parser/tests/mod.rs
cyb/evy/forks/bevy_ecs/src/storage/mod.rs
cyb/evy/forks/bevy_tasks/src/iter/mod.rs
soft3/glia/run/arch/decoder/families/mod.rs
cyb/wysm/crates/wasmi/src/func/mod.rs
cyb/evy/forks/naga/src/common/mod.rs
cyb/evy/forks/naga/src/front/wgsl/mod.rs
cyb/evy/forks/naga/src/back/spv/mod.rs
cyb/evy/forks/naga/src/back/dot/mod.rs
cyb/evy/forks/bevy_render/src/view/window/mod.rs
cyb/wysm/crates/wasi/src/sync/snapshots/mod.rs
cyb/evy/forks/bevy_render/src/experimental/occlusion_culling/mod.rs
cyb/evy/forks/bevy_ecs/src/schedule/graph/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/mod.rs
cyb/wysm/crates/wasmi/src/module/parser/mod.rs
cyb/wysm/crates/wasmi/src/engine/limits/mod.rs
cyb/wysm/crates/wasmi/src/engine/executor/mod.rs
cyb/evy/forks/bevy_ecs/src/system/commands/mod.rs
cyb/evy/forks/naga/src/back/wgsl/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/oit/resolve/mod.rs
cyb/wysm/crates/wasmi/src/module/instantiate/mod.rs
cyb/evy/forks/bevy_core_pipeline/src/experimental/mip_generation/mod.rs
cyb/evy/forks/bevy_ecs/src/storage/table/mod.rs
bootloader/go-cyber/cw/packages/cyber-std/src/tokenfactory/mod.rs
cyb/evy/forks/bevy_render/src/view/visibility/mod.rs
cyb/evy/forks/bevy_ecs/src/schedule/executor/mod.rs
cyb/evy/forks/naga/src/front/spv/mod.rs
cyb/evy/forks/naga/src/back/msl/mod.rs
cyb/evy/forks/naga/src/front/glsl/mod.rs
cyb/evy/forks/bevy_ecs/src/world/entity_access/mod.rs
cyb/evy/forks/bevy_mesh/src/primitives/dim3/mod.rs
cyb/evy/forks/naga/src/back/glsl/mod.rs
cyb/evy/forks/naga/src/back/hlsl/mod.rs
struct Baz { m: mat3x2, } struct Baz { float2 m_0; float2 m_1; float2 m_2; }; float3x2 GetMatmOnBaz(Baz obj) { return float3x2(obj.m_0, obj.m_1, obj.m_2); }
cyb/wysm/crates/wasmi/src/engine/executor/handler/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/func/mod.rs
cyb/evy/forks/naga/src/front/wgsl/parse/mod.rs
cyb/evy/forks/naga/src/back/wgsl/polyfill/mod.rs
cyb/evy/forks/naga/src/front/wgsl/lower/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/func/simd/mod.rs
cyb/wysm/crates/wasmi/src/engine/translator/func/stack/mod.rs
cyb/wysm/crates/wasmi/src/engine/executor/handler/dispatch/mod.rs

Graph