diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2022-10-25 17:57:33 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-25 17:57:33 +0530 |
commit | f242d98280a7b261af9bf458498915d973f8d48e (patch) | |
tree | 5d215617126330e63d1b9102c77185b80e1799f4 | |
parent | 34fb380ed38ff324202b7779ae850edab133e577 (diff) |
perf(core): avoid isolate slots for ModuleMap (#16409)
-rw-r--r-- | core/runtime.rs | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/core/runtime.rs b/core/runtime.rs index 3ccff9af7..a157a56ce 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -78,6 +78,7 @@ struct IsolateAllocations { /// and an optional zero copy buffer, each async Op is tied to a Promise in JavaScript. pub struct JsRuntime { state: Rc<RefCell<JsRuntimeState>>, + module_map: Option<Rc<RefCell<ModuleMap>>>, // This is an Option<OwnedIsolate> instead of just OwnedIsolate to workaround // a safety issue with SnapshotCreator. See JsRuntime::drop. v8_isolate: Option<v8::OwnedIsolate>, @@ -448,7 +449,7 @@ impl JsRuntime { let module_map_rc = Rc::new(RefCell::new(ModuleMap::new(loader, op_state))); isolate.set_data( Self::MODULE_MAP_DATA_OFFSET, - Rc::into_raw(module_map_rc) as *mut c_void, + Rc::into_raw(module_map_rc.clone()) as *mut c_void, ); let mut js_runtime = Self { @@ -458,6 +459,7 @@ impl JsRuntime { event_loop_middlewares: Vec::with_capacity(options.extensions.len()), extensions: options.extensions, state: state_rc, + module_map: Some(module_map_rc), }; // Init resources and ops before extensions to make sure they are @@ -492,6 +494,11 @@ impl JsRuntime { } #[inline] + fn get_module_map(&mut self) -> &Rc<RefCell<ModuleMap>> { + self.module_map.as_ref().unwrap() + } + + #[inline] pub fn global_context(&mut self) -> v8::Global<v8::Context> { self.global_realm().0 } @@ -782,6 +789,7 @@ impl JsRuntime { // Drop existing ModuleMap to drop v8::Global handles { + self.module_map.take(); let v8_isolate = self.v8_isolate(); Self::drop_state_and_module_map(v8_isolate); } @@ -964,7 +972,6 @@ impl JsRuntime { ) -> Poll<Result<(), Error>> { // We always poll the inspector first let _ = self.inspector().borrow_mut().poll_unpin(cx); - let module_map_rc = Self::module_map(self.v8_isolate()); { let state = self.state.borrow(); state.waker.register(cx.waker()); @@ -1033,7 +1040,6 @@ impl JsRuntime { } let mut state = self.state.borrow_mut(); - let module_map = module_map_rc.borrow(); // Check if more async ops have been dispatched // during this turn of event loop. @@ -1075,6 +1081,7 @@ impl JsRuntime { } else if state.dyn_module_evaluate_idle_counter >= 1 { let mut msg = "Dynamically imported module evaluation is still pending but there are no pending ops. This situation is often caused by unresolved promises. Pending dynamic modules:\n".to_string(); + let module_map = self.module_map.as_mut().unwrap().borrow_mut(); for pending_evaluate in &state.pending_dyn_mod_evaluate { let module_info = module_map .get_info_by_id(&pending_evaluate.module_id) @@ -1097,9 +1104,8 @@ Pending dynamic modules:\n".to_string(); fn event_loop_pending_state(&mut self) -> EventLoopPendingState { let isolate = self.v8_isolate.as_mut().unwrap(); - let module_map_rc = Self::module_map(isolate); let state = self.state.borrow_mut(); - let module_map = module_map_rc.borrow(); + let module_map = self.module_map.as_mut().unwrap().borrow(); EventLoopPendingState { has_pending_refed_ops: state.pending_ops.len() > state.unrefed_ops.len(), @@ -1524,12 +1530,17 @@ impl JsRuntime { &mut self, cx: &mut Context, ) -> Poll<Result<(), Error>> { - let module_map_rc = Self::module_map(self.v8_isolate()); - - if module_map_rc.borrow().preparing_dynamic_imports.is_empty() { + if self + .get_module_map() + .borrow() + .preparing_dynamic_imports + .is_empty() + { return Poll::Ready(Ok(())); } + let module_map_rc = self.get_module_map().clone(); + loop { let poll_result = module_map_rc .borrow_mut() @@ -1562,12 +1573,17 @@ impl JsRuntime { } fn poll_dyn_imports(&mut self, cx: &mut Context) -> Poll<Result<(), Error>> { - let module_map_rc = Self::module_map(self.v8_isolate()); - - if module_map_rc.borrow().pending_dynamic_imports.is_empty() { + if self + .get_module_map() + .borrow() + .pending_dynamic_imports + .is_empty() + { return Poll::Ready(Ok(())); } + let module_map_rc = self.get_module_map().clone(); + loop { let poll_result = module_map_rc .borrow_mut() @@ -1653,16 +1669,15 @@ impl JsRuntime { /// resolved or rejected the promise. If the promise is still pending /// then another turn of event loop must be performed. fn evaluate_pending_module(&mut self) { - let state_rc = self.state.clone(); - let maybe_module_evaluation = - state_rc.borrow_mut().pending_mod_evaluate.take(); + self.state.borrow_mut().pending_mod_evaluate.take(); if maybe_module_evaluation.is_none() { return; } let mut module_evaluation = maybe_module_evaluation.unwrap(); + let state_rc = self.state.clone(); let scope = &mut self.handle_scope(); let promise_global = module_evaluation.promise.clone().unwrap(); @@ -1703,10 +1718,13 @@ impl JsRuntime { // Returns true if some dynamic import was resolved. fn evaluate_dyn_imports(&mut self) -> bool { - let mut resolved_any = false; - let mut still_pending = vec![]; let pending = std::mem::take(&mut self.state.borrow_mut().pending_dyn_mod_evaluate); + if pending.is_empty() { + return false; + } + let mut resolved_any = false; + let mut still_pending = vec![]; for pending_dyn_evaluate in pending { let maybe_result = { let scope = &mut self.handle_scope(); |