mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
feat: support serializing WebAssembly.Module
objects (#12140)
This commit is contained in:
parent
5b526e5d17
commit
cdb252af0a
10 changed files with 96 additions and 24 deletions
|
@ -134,6 +134,7 @@ fn create_web_worker_callback(ps: ProcState) -> Arc<CreateWebWorkerCb> {
|
|||
blob_store: ps.blob_store.clone(),
|
||||
broadcast_channel: ps.broadcast_channel.clone(),
|
||||
shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()),
|
||||
compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()),
|
||||
cpu_count: num_cpus::get(),
|
||||
};
|
||||
|
||||
|
@ -222,6 +223,7 @@ pub fn create_main_worker(
|
|||
blob_store: ps.blob_store.clone(),
|
||||
broadcast_channel: ps.broadcast_channel.clone(),
|
||||
shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()),
|
||||
compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()),
|
||||
cpu_count: num_cpus::get(),
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ use deno_core::error::Context;
|
|||
use deno_core::parking_lot::Mutex;
|
||||
use deno_core::resolve_url;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::ModuleSource;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::SharedArrayBufferStore;
|
||||
|
@ -66,6 +67,7 @@ pub struct Inner {
|
|||
pub blob_store: BlobStore,
|
||||
pub broadcast_channel: InMemoryBroadcastChannel,
|
||||
pub shared_array_buffer_store: SharedArrayBufferStore,
|
||||
pub compiled_wasm_module_store: CompiledWasmModuleStore,
|
||||
}
|
||||
|
||||
impl Deref for ProcState {
|
||||
|
@ -155,6 +157,7 @@ impl ProcState {
|
|||
let blob_store = BlobStore::default();
|
||||
let broadcast_channel = InMemoryBroadcastChannel::default();
|
||||
let shared_array_buffer_store = SharedArrayBufferStore::default();
|
||||
let compiled_wasm_module_store = CompiledWasmModuleStore::default();
|
||||
|
||||
let file_fetcher = FileFetcher::new(
|
||||
http_cache,
|
||||
|
@ -225,6 +228,7 @@ impl ProcState {
|
|||
blob_store,
|
||||
broadcast_channel,
|
||||
shared_array_buffer_store,
|
||||
compiled_wasm_module_store,
|
||||
})))
|
||||
}
|
||||
|
||||
|
|
|
@ -252,6 +252,7 @@ pub async fn run(
|
|||
blob_store,
|
||||
broadcast_channel,
|
||||
shared_array_buffer_store: None,
|
||||
compiled_wasm_module_store: None,
|
||||
cpu_count: num_cpus::get(),
|
||||
};
|
||||
let mut worker =
|
||||
|
|
|
@ -665,6 +665,23 @@ impl<'a> v8::ValueSerializerImpl for SerializeDeserialize<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_wasm_module_transfer_id(
|
||||
&mut self,
|
||||
scope: &mut HandleScope<'_>,
|
||||
module: Local<v8::WasmModuleObject>,
|
||||
) -> Option<u32> {
|
||||
let state_rc = JsRuntime::state(scope);
|
||||
let state = state_rc.borrow_mut();
|
||||
if let Some(compiled_wasm_module_store) = &state.compiled_wasm_module_store
|
||||
{
|
||||
let compiled_wasm_module = module.get_compiled_module();
|
||||
let id = compiled_wasm_module_store.insert(compiled_wasm_module);
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn write_host_object<'s>(
|
||||
&mut self,
|
||||
scope: &mut v8::HandleScope<'s>,
|
||||
|
@ -704,6 +721,22 @@ impl<'a> v8::ValueDeserializerImpl for SerializeDeserialize<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_wasm_module_from_id<'s>(
|
||||
&mut self,
|
||||
scope: &mut HandleScope<'s>,
|
||||
clone_id: u32,
|
||||
) -> Option<Local<'s, v8::WasmModuleObject>> {
|
||||
let state_rc = JsRuntime::state(scope);
|
||||
let state = state_rc.borrow_mut();
|
||||
if let Some(compiled_wasm_module_store) = &state.compiled_wasm_module_store
|
||||
{
|
||||
let compiled_module = compiled_wasm_module_store.take(clone_id)?;
|
||||
v8::WasmModuleObject::from_compiled_module(scope, &compiled_module)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn read_host_object<'s>(
|
||||
&mut self,
|
||||
scope: &mut v8::HandleScope<'s>,
|
||||
|
|
|
@ -58,6 +58,7 @@ pub use crate::modules::ModuleLoader;
|
|||
pub use crate::modules::ModuleSource;
|
||||
pub use crate::modules::ModuleSourceFuture;
|
||||
pub use crate::modules::NoopModuleLoader;
|
||||
pub use crate::runtime::CompiledWasmModuleStore;
|
||||
pub use crate::runtime::SharedArrayBufferStore;
|
||||
// TODO(bartlomieju): this struct should be implementation
|
||||
// detail nad not be public
|
||||
|
|
|
@ -99,36 +99,48 @@ struct ModEvaluate {
|
|||
sender: oneshot::Sender<Result<(), AnyError>>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct SharedArrayBufferStore(Arc<Mutex<SharedArrayBufferStoreInner>>);
|
||||
pub struct CrossIsolateStore<T>(Arc<Mutex<CrossIsolateStoreInner<T>>>);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SharedArrayBufferStoreInner {
|
||||
buffers: HashMap<u32, v8::SharedRef<v8::BackingStore>>,
|
||||
struct CrossIsolateStoreInner<T> {
|
||||
map: HashMap<u32, T>,
|
||||
last_id: u32,
|
||||
}
|
||||
|
||||
impl SharedArrayBufferStore {
|
||||
pub(crate) fn insert(
|
||||
&self,
|
||||
backing_store: v8::SharedRef<v8::BackingStore>,
|
||||
) -> u32 {
|
||||
let mut buffers = self.0.lock().unwrap();
|
||||
let last_id = buffers.last_id;
|
||||
buffers.buffers.insert(last_id, backing_store);
|
||||
buffers.last_id += 1;
|
||||
impl<T> CrossIsolateStore<T> {
|
||||
pub(crate) fn insert(&self, value: T) -> u32 {
|
||||
let mut store = self.0.lock().unwrap();
|
||||
let last_id = store.last_id;
|
||||
store.map.insert(last_id, value);
|
||||
store.last_id += 1;
|
||||
last_id
|
||||
}
|
||||
|
||||
pub(crate) fn take(
|
||||
&self,
|
||||
id: u32,
|
||||
) -> Option<v8::SharedRef<v8::BackingStore>> {
|
||||
let mut buffers = self.0.lock().unwrap();
|
||||
buffers.buffers.remove(&id)
|
||||
pub(crate) fn take(&self, id: u32) -> Option<T> {
|
||||
let mut store = self.0.lock().unwrap();
|
||||
store.map.remove(&id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for CrossIsolateStore<T> {
|
||||
fn default() -> Self {
|
||||
CrossIsolateStore(Arc::new(Mutex::new(CrossIsolateStoreInner {
|
||||
map: Default::default(),
|
||||
last_id: 0,
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for CrossIsolateStore<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub type SharedArrayBufferStore =
|
||||
CrossIsolateStore<v8::SharedRef<v8::BackingStore>>;
|
||||
|
||||
pub type CompiledWasmModuleStore = CrossIsolateStore<v8::CompiledWasmModule>;
|
||||
|
||||
/// Internal state for JsRuntime which is stored in one of v8::Isolate's
|
||||
/// embedder slots.
|
||||
pub(crate) struct JsRuntimeState {
|
||||
|
@ -149,6 +161,7 @@ pub(crate) struct JsRuntimeState {
|
|||
pub(crate) have_unpolled_ops: bool,
|
||||
pub(crate) op_state: Rc<RefCell<OpState>>,
|
||||
pub(crate) shared_array_buffer_store: Option<SharedArrayBufferStore>,
|
||||
pub(crate) compiled_wasm_module_store: Option<CompiledWasmModuleStore>,
|
||||
waker: AtomicWaker,
|
||||
}
|
||||
|
||||
|
@ -238,11 +251,20 @@ pub struct RuntimeOptions {
|
|||
/// (which it only does once), otherwise it's silenty dropped.
|
||||
pub v8_platform: Option<v8::SharedRef<v8::Platform>>,
|
||||
|
||||
/// The buffer to use for transferring SharedArrayBuffers between isolates.
|
||||
/// The store to use for transferring SharedArrayBuffers between isolates.
|
||||
/// If multiple isolates should have the possibility of sharing
|
||||
/// SharedArrayBuffers, they should use the same SharedArrayBufferStore. If no
|
||||
/// SharedArrayBufferStore is specified, SharedArrayBuffer can not be serialized.
|
||||
/// SharedArrayBuffers, they should use the same [SharedArrayBufferStore]. If
|
||||
/// no [SharedArrayBufferStore] is specified, SharedArrayBuffer can not be
|
||||
/// serialized.
|
||||
pub shared_array_buffer_store: Option<SharedArrayBufferStore>,
|
||||
|
||||
/// The store to use for transferring `WebAssembly.Module` objects between
|
||||
/// isolates.
|
||||
/// If multiple isolates should have the possibility of sharing
|
||||
/// `WebAssembly.Module` objects, they should use the same
|
||||
/// [CompiledWasmModuleStore]. If no [CompiledWasmModuleStore] is specified,
|
||||
/// `WebAssembly.Module` objects cannot be serialized.
|
||||
pub compiled_wasm_module_store: Option<CompiledWasmModuleStore>,
|
||||
}
|
||||
|
||||
impl JsRuntime {
|
||||
|
@ -334,6 +356,7 @@ impl JsRuntime {
|
|||
pending_ops: FuturesUnordered::new(),
|
||||
pending_unref_ops: FuturesUnordered::new(),
|
||||
shared_array_buffer_store: options.shared_array_buffer_store,
|
||||
compiled_wasm_module_store: options.compiled_wasm_module_store,
|
||||
op_state: op_state.clone(),
|
||||
have_unpolled_ops: false,
|
||||
waker: AtomicWaker::new(),
|
||||
|
|
|
@ -46,6 +46,7 @@ async fn main() -> Result<(), AnyError> {
|
|||
blob_store: BlobStore::default(),
|
||||
broadcast_channel: InMemoryBroadcastChannel::default(),
|
||||
shared_array_buffer_store: None,
|
||||
compiled_wasm_module_store: None,
|
||||
cpu_count: 1,
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ use deno_core::serde_json;
|
|||
use deno_core::serde_json::json;
|
||||
use deno_core::v8;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::Extension;
|
||||
use deno_core::GetErrorClassFn;
|
||||
use deno_core::JsErrorCreateFn;
|
||||
|
@ -285,6 +286,7 @@ pub struct WebWorkerOptions {
|
|||
pub blob_store: BlobStore,
|
||||
pub broadcast_channel: InMemoryBroadcastChannel,
|
||||
pub shared_array_buffer_store: Option<SharedArrayBufferStore>,
|
||||
pub compiled_wasm_module_store: Option<CompiledWasmModuleStore>,
|
||||
pub cpu_count: usize,
|
||||
}
|
||||
|
||||
|
@ -384,6 +386,7 @@ impl WebWorker {
|
|||
js_error_create_fn: options.js_error_create_fn.clone(),
|
||||
get_error_class_fn: options.get_error_class_fn,
|
||||
shared_array_buffer_store: options.shared_array_buffer_store.clone(),
|
||||
compiled_wasm_module_store: options.compiled_wasm_module_store.clone(),
|
||||
extensions,
|
||||
..Default::default()
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ use deno_core::located_script_name;
|
|||
use deno_core::serde_json;
|
||||
use deno_core::serde_json::json;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::Extension;
|
||||
use deno_core::GetErrorClassFn;
|
||||
use deno_core::JsErrorCreateFn;
|
||||
|
@ -73,6 +74,7 @@ pub struct WorkerOptions {
|
|||
pub blob_store: BlobStore,
|
||||
pub broadcast_channel: InMemoryBroadcastChannel,
|
||||
pub shared_array_buffer_store: Option<SharedArrayBufferStore>,
|
||||
pub compiled_wasm_module_store: Option<CompiledWasmModuleStore>,
|
||||
pub cpu_count: usize,
|
||||
}
|
||||
|
||||
|
@ -156,6 +158,7 @@ impl MainWorker {
|
|||
js_error_create_fn: options.js_error_create_fn.clone(),
|
||||
get_error_class_fn: options.get_error_class_fn,
|
||||
shared_array_buffer_store: options.shared_array_buffer_store.clone(),
|
||||
compiled_wasm_module_store: options.compiled_wasm_module_store.clone(),
|
||||
extensions,
|
||||
..Default::default()
|
||||
});
|
||||
|
@ -345,6 +348,7 @@ mod tests {
|
|||
blob_store: BlobStore::default(),
|
||||
broadcast_channel: InMemoryBroadcastChannel::default(),
|
||||
shared_array_buffer_store: None,
|
||||
compiled_wasm_module_store: None,
|
||||
cpu_count: 1,
|
||||
};
|
||||
|
||||
|
|
|
@ -13573,7 +13573,7 @@
|
|||
"module": {
|
||||
"serialization-via-idb.any.html": false,
|
||||
"serialization-via-notifications-api.any.html": false,
|
||||
"nested-worker-success.any.worker.html": false
|
||||
"nested-worker-success.any.worker.html": true
|
||||
},
|
||||
"arraybuffer": {
|
||||
"transfer.window.html": false
|
||||
|
|
Loading…
Reference in a new issue