summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs200
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