Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin_runner): shared runtime engine #109

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions crates/swc_plugin_runner/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ use wasmer::{Module, Store};
#[cfg(all(not(target_arch = "wasm32"), feature = "filesystem_cache"))]
use wasmer_cache::{Cache as WasmerCache, FileSystemCache, Hash};

use crate::plugin_module_bytes::{
CompiledPluginModuleBytes, PluginModuleBytes, RawPluginModuleBytes,
use crate::{
plugin_module_bytes::{CompiledPluginModuleBytes, PluginModuleBytes, RawPluginModuleBytes},
wasix_runtime::new_store,
};

/// Version for bytecode cache stored in local filesystem.
Expand Down Expand Up @@ -114,7 +115,7 @@ impl PluginModuleCacheInner {
// If FilesystemCache is available, store serialized bytes into fs.
if let Some(fs_cache_store) = &mut self.fs_cache_store {
let module_bytes_hash = Hash::generate(&raw_module_bytes);
let store = crate::plugin_module_bytes::new_store();
let store = new_store();
let module = Module::new(&store, raw_module_bytes.clone())
.context("Cannot compile plugin binary")?;
fs_cache_store.store(module_bytes_hash, &module)?;
Expand Down Expand Up @@ -154,7 +155,7 @@ impl PluginModuleCacheInner {
#[cfg(all(not(target_arch = "wasm32"), feature = "filesystem_cache"))]
if let Some(fs_cache_store) = &self.fs_cache_store {
let hash = self.fs_cache_hash_store.get(key)?;
let store = crate::plugin_module_bytes::new_store();
let store = new_store();
let module = unsafe { fs_cache_store.load(&store, *hash) };
if let Ok(module) = module {
return Some(Box::new(CompiledPluginModuleBytes::new(
Expand Down
31 changes: 1 addition & 30 deletions crates/swc_plugin_runner/src/plugin_module_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,7 @@ use anyhow::Error;
use serde::{Deserialize, Serialize};
use wasmer::{Module, Store};

/// Creates an instnace of [Store].
///
/// This function exists because we need to disable simd.
#[cfg(not(target_arch = "wasm32"))]
#[allow(unused_mut)]
pub(crate) fn new_store() -> Store {
// Use empty enumset to disable simd.
use enumset::EnumSet;
use wasmer::{BaseTunables, CompilerConfig, EngineBuilder, Target, Triple};
let mut set = EnumSet::new();

// [TODO]: Should we use is_x86_feature_detected! macro instead?
#[cfg(target_arch = "x86_64")]
set.insert(wasmer::CpuFeature::SSE2);
let target = Target::new(Triple::host(), set);

let config = wasmer_compiler_cranelift::Cranelift::default();
let mut engine = EngineBuilder::new(Box::new(config) as Box<dyn CompilerConfig>)
.set_target(Some(target))
.engine();
let tunables = BaseTunables::for_target(engine.target());
engine.set_tunables(tunables);

Store::new(engine)
}

#[cfg(target_arch = "wasm32")]
fn new_store() -> Store {
Store::default()
}
use crate::wasix_runtime::new_store;

// A trait abstracts plugin's wasm compilation and instantiation.
// Depends on the caller, this could be a simple clone from existing module, or
Expand Down
46 changes: 44 additions & 2 deletions crates/swc_plugin_runner/src/wasix_runtime.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
use std::{path::PathBuf, sync::Arc};

use parking_lot::Mutex;
use swc_common::sync::{Lazy, OnceCell};
use wasmer::Store;
use wasmer_wasix::Runtime;

/// A shared instance to plugin runtime engine.
/// ref: https://github.com/wasmerio/wasmer/issues/3793#issuecomment-1607117480
static ENGINE: Lazy<Mutex<wasmer::Engine>> = Lazy::new(|| {
// Use empty enumset to disable simd.
use enumset::EnumSet;
use wasmer::{BaseTunables, CompilerConfig, EngineBuilder, Target, Triple};
let mut set = EnumSet::new();

// [TODO]: Should we use is_x86_feature_detected! macro instead?
#[cfg(target_arch = "x86_64")]
set.insert(wasmer::CpuFeature::SSE2);
let target = Target::new(Triple::host(), set);

let config = wasmer_compiler_cranelift::Cranelift::default();
let mut engine = EngineBuilder::new(Box::new(config) as Box<dyn CompilerConfig>)
.set_target(Some(target))
.engine();
let tunables = BaseTunables::for_target(engine.target());
engine.set_tunables(tunables);
parking_lot::Mutex::new(wasmer::Engine::from(engine))
});

/// Dummy http client for wasix runtime to avoid instantiation failure for the
/// default pluggable runtime. We don't support network in the host runtime
/// anyway (we init vnet instead), and for the default runtime mostly it's for
/// the wapm registry which is redundant for the plugin.
#[derive(Debug)]
struct StubHttpClient;

Expand Down Expand Up @@ -38,11 +67,10 @@ pub fn build_wasi_runtime(
SharedCache::default().with_fallback(wasmer_wasix::runtime::module_cache::in_memory());

let dummy_loader = BuiltinPackageLoader::new_with_client(".", Arc::new(StubHttpClient));

let rt = PluggableRuntime {
rt: Arc::new(TokioTaskManager::shared()),
networking: Arc::new(virtual_net::UnsupportedVirtualNetworking::default()),
engine: Some(wasmer::Engine::default()),
engine: Some(ENGINE.lock().clone()),
tty: None,
source: Arc::new(MultiSource::new()),
module_cache: Arc::new(cache),
Expand All @@ -52,3 +80,17 @@ pub fn build_wasi_runtime(

Some(Arc::new(rt))
}

/// Creates an instnace of [Store] with custom engine instead of default one to
/// disable simd for certain platform targets
#[cfg(not(target_arch = "wasm32"))]
#[allow(unused_mut)]
pub(crate) fn new_store() -> Store {
let engine = ENGINE.lock().clone();
Store::new(engine)
}

#[cfg(target_arch = "wasm32")]
pub(crate) fn new_store() -> Store {
Store::default()
}