diff options
Diffstat (limited to 'core/runtime.rs')
-rw-r--r-- | core/runtime.rs | 200 |
1 files changed, 39 insertions, 161 deletions
diff --git a/core/runtime.rs b/core/runtime.rs index ef6d4d2f2..c19765dd9 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -17,6 +17,7 @@ use crate::modules::ModuleMap; use crate::op_void_async; use crate::op_void_sync; use crate::ops::*; +use crate::snapshot_util; use crate::source_map::SourceMapCache; use crate::source_map::SourceMapGetter; use crate::Extension; @@ -86,7 +87,7 @@ pub struct JsRuntime { // This is an Option<OwnedIsolate> instead of just OwnedIsolate to workaround // a safety issue with SnapshotCreator. See JsRuntime::drop. v8_isolate: Option<v8::OwnedIsolate>, - snapshot_options: SnapshotOptions, + snapshot_options: snapshot_util::SnapshotOptions, allocations: IsolateAllocations, extensions: Vec<Extension>, event_loop_middlewares: Vec<Box<OpEventLoopFn>>, @@ -298,32 +299,6 @@ pub struct RuntimeOptions { pub is_main: bool, } -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum SnapshotOptions { - Load, - CreateFromExisting, - Create, - None, -} - -impl SnapshotOptions { - pub fn loaded(&self) -> bool { - matches!( - self, - SnapshotOptions::Load | SnapshotOptions::CreateFromExisting - ) - } - - fn from_bools(snapshot_loaded: bool, will_snapshot: bool) -> Self { - match (snapshot_loaded, will_snapshot) { - (true, true) => SnapshotOptions::CreateFromExisting, - (false, true) => SnapshotOptions::Create, - (true, false) => SnapshotOptions::Load, - (false, false) => SnapshotOptions::None, - } - } -} - impl Drop for JsRuntime { fn drop(&mut self) { if let Some(v8_isolate) = self.v8_isolate.as_mut() { @@ -410,113 +385,30 @@ impl JsRuntime { .collect::<Vec<_>>() .into_boxed_slice(); - let refs = bindings::external_references(&op_ctxs, !options.will_snapshot); + let snapshot_options = snapshot_util::SnapshotOptions::from_bools( + options.startup_snapshot.is_some(), + options.will_snapshot, + ); + let refs = bindings::external_references(&op_ctxs, snapshot_options); // V8 takes ownership of external_references. let refs: &'static v8::ExternalReferences = Box::leak(Box::new(refs)); let global_context; - let mut module_map_data = None; - let mut module_handles = vec![]; - - fn get_context_data( - scope: &mut v8::HandleScope<()>, - context: v8::Local<v8::Context>, - ) -> (Vec<v8::Global<v8::Module>>, v8::Global<v8::Array>) { - fn data_error_to_panic(err: v8::DataError) -> ! { - match err { - v8::DataError::BadType { actual, expected } => { - panic!( - "Invalid type for snapshot data: expected {expected}, got {actual}" - ); - } - v8::DataError::NoData { expected } => { - panic!("No data for snapshot data: expected {expected}"); - } - } - } + let mut maybe_snapshotted_data = None; - let mut scope = v8::ContextScope::new(scope, context); - // The 0th element is the module map itself, followed by X number of module - // handles. We need to deserialize the "next_module_id" field from the - // map to see how many module handles we expect. - match scope.get_context_data_from_snapshot_once::<v8::Array>(0) { - Ok(val) => { - let next_module_id = { - let info_data: v8::Local<v8::Array> = - val.get_index(&mut scope, 1).unwrap().try_into().unwrap(); - info_data.length() - }; - - // Over allocate so executing a few scripts doesn't have to resize this vec. - let mut module_handles = - Vec::with_capacity(next_module_id as usize + 16); - for i in 1..=next_module_id { - match scope - .get_context_data_from_snapshot_once::<v8::Module>(i as usize) - { - Ok(val) => { - let module_global = v8::Global::new(&mut scope, val); - module_handles.push(module_global); - } - Err(err) => data_error_to_panic(err), - } - } - - (module_handles, v8::Global::new(&mut scope, val)) - } - Err(err) => data_error_to_panic(err), - } - } - - let (mut isolate, snapshot_options) = if options.will_snapshot { - let (snapshot_creator, snapshot_loaded) = - if let Some(snapshot) = options.startup_snapshot { - ( - match snapshot { - Snapshot::Static(data) => { - v8::Isolate::snapshot_creator_from_existing_snapshot( - data, - Some(refs), - ) - } - Snapshot::JustCreated(data) => { - v8::Isolate::snapshot_creator_from_existing_snapshot( - data, - Some(refs), - ) - } - Snapshot::Boxed(data) => { - v8::Isolate::snapshot_creator_from_existing_snapshot( - data, - Some(refs), - ) - } - }, - true, - ) - } else { - (v8::Isolate::snapshot_creator(Some(refs)), false) - }; - - let snapshot_options = - SnapshotOptions::from_bools(snapshot_loaded, options.will_snapshot); + let (mut isolate, snapshot_options) = if snapshot_options.will_snapshot() { + let snapshot_creator = + snapshot_util::create_snapshot_creator(refs, options.startup_snapshot); let mut isolate = JsRuntime::setup_isolate(snapshot_creator); { - // SAFETY: this is first use of `isolate_ptr` so we are sure we're - // not overwriting an existing pointer. - isolate = unsafe { - isolate_ptr.write(isolate); - isolate_ptr.read() - }; let scope = &mut v8::HandleScope::new(&mut isolate); let context = bindings::initialize_context(scope, &op_ctxs, snapshot_options); // Get module map data from the snapshot if has_startup_snapshot { - let context_data = get_context_data(scope, context); - module_handles = context_data.0; - module_map_data = Some(context_data.1); + maybe_snapshotted_data = + Some(snapshot_util::get_snapshotted_data(scope, context)); } global_context = v8::Global::new(scope, context); @@ -534,38 +426,26 @@ impl JsRuntime { ) }) .external_references(&**refs); - let snapshot_loaded = if let Some(snapshot) = options.startup_snapshot { + + if let Some(snapshot) = options.startup_snapshot { params = match snapshot { Snapshot::Static(data) => params.snapshot_blob(data), Snapshot::JustCreated(data) => params.snapshot_blob(data), Snapshot::Boxed(data) => params.snapshot_blob(data), }; - true - } else { - false - }; - - let snapshot_options = - SnapshotOptions::from_bools(snapshot_loaded, options.will_snapshot); + } let isolate = v8::Isolate::new(params); let mut isolate = JsRuntime::setup_isolate(isolate); { - // SAFETY: this is first use of `isolate_ptr` so we are sure we're - // not overwriting an existing pointer. - isolate = unsafe { - isolate_ptr.write(isolate); - isolate_ptr.read() - }; let scope = &mut v8::HandleScope::new(&mut isolate); let context = bindings::initialize_context(scope, &op_ctxs, snapshot_options); // Get module map data from the snapshot if has_startup_snapshot { - let context_data = get_context_data(scope, context); - module_handles = context_data.0; - module_map_data = Some(context_data.1); + maybe_snapshotted_data = + Some(snapshot_util::get_snapshotted_data(scope, context)); } global_context = v8::Global::new(scope, context); @@ -574,6 +454,12 @@ impl JsRuntime { (isolate, snapshot_options) }; + // SAFETY: this is first use of `isolate_ptr` so we are sure we're + // not overwriting an existing pointer. + isolate = unsafe { + isolate_ptr.write(isolate); + isolate_ptr.read() + }; global_context.open(&mut isolate).set_slot( &mut isolate, Rc::new(RefCell::new(ContextState { @@ -593,7 +479,7 @@ impl JsRuntime { None }; - let loader = if snapshot_options != SnapshotOptions::Load { + let loader = if snapshot_options != snapshot_util::SnapshotOptions::Load { let esm_sources = options .extensions .iter() @@ -604,7 +490,7 @@ impl JsRuntime { .collect::<Vec<ExtensionFileSource>>(); #[cfg(feature = "include_js_files_for_snapshotting")] - if snapshot_options != SnapshotOptions::None { + if snapshot_options != snapshot_util::SnapshotOptions::None { for source in &esm_sources { use crate::ExtensionFileSourceCode; if let ExtensionFileSourceCode::LoadedFromFsDuringSnapshot(path) = @@ -642,17 +528,13 @@ impl JsRuntime { let module_map_rc = Rc::new(RefCell::new(ModuleMap::new( loader, op_state, - snapshot_options == SnapshotOptions::Load, + snapshot_options == snapshot_util::SnapshotOptions::Load, ))); - if let Some(module_map_data) = module_map_data { + if let Some(snapshotted_data) = maybe_snapshotted_data { let scope = &mut v8::HandleScope::with_context(&mut isolate, global_context); let mut module_map = module_map_rc.borrow_mut(); - module_map.update_with_snapshot_data( - scope, - module_map_data, - module_handles, - ); + module_map.update_with_snapshotted_data(scope, snapshotted_data); } isolate.set_data( Self::MODULE_MAP_DATA_OFFSET, @@ -1061,23 +943,19 @@ impl JsRuntime { // Serialize the module map and store its data in the snapshot. { - let module_map_rc = self.module_map.take().unwrap(); - let module_map = module_map_rc.borrow(); - let (module_map_data, module_handles) = - module_map.serialize_for_snapshotting(&mut self.handle_scope()); + let snapshotted_data = { + let module_map_rc = self.module_map.take().unwrap(); + let module_map = module_map_rc.borrow(); + module_map.serialize_for_snapshotting(&mut self.handle_scope()) + }; let context = self.global_context(); let mut scope = self.handle_scope(); - let local_context = v8::Local::new(&mut scope, context); - let local_data = v8::Local::new(&mut scope, module_map_data); - let offset = scope.add_context_data(local_context, local_data); - assert_eq!(offset, 0); - - for (index, handle) in module_handles.into_iter().enumerate() { - let module_handle = v8::Local::new(&mut scope, handle); - let offset = scope.add_context_data(local_context, module_handle); - assert_eq!(offset, index + 1); - } + snapshot_util::set_snapshotted_data( + &mut scope, + context, + snapshotted_data, + ); } // Drop existing ModuleMap to drop v8::Global handles |