summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-10-25 17:57:33 +0530
committerGitHub <noreply@github.com>2022-10-25 17:57:33 +0530
commitf242d98280a7b261af9bf458498915d973f8d48e (patch)
tree5d215617126330e63d1b9102c77185b80e1799f4 /core/runtime.rs
parent34fb380ed38ff324202b7779ae850edab133e577 (diff)
perf(core): avoid isolate slots for ModuleMap (#16409)
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs50
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();