From 3a1b22aec26e68a4af664f765d2e88156f7c02c0 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 7 Jul 2023 12:04:09 -0700 Subject: [PATCH 1/2] Use linear scans on contexts --- packages/core/src/scopes.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index 2e4bf3651..56ca77608 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -11,7 +11,7 @@ use crate::{ }; use bumpalo::{boxed::Box as BumpBox, Bump}; use bumpslab::{BumpSlab, Slot}; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashSet; use slab::{Slab, VacantEntry}; use std::{ any::{Any, TypeId}, @@ -173,7 +173,7 @@ pub struct ScopeState { pub(crate) hooks: RefCell>>>, pub(crate) hook_idx: Cell, - pub(crate) shared_contexts: RefCell>>, + pub(crate) shared_contexts: RefCell)>>, pub(crate) tasks: Rc, pub(crate) spawned_tasks: RefCell>, @@ -347,7 +347,9 @@ impl<'src> ScopeState { pub fn has_context(&self) -> Option { self.shared_contexts .borrow() - .get(&TypeId::of::())? + .iter() + .find(|(k, _)| *k == TypeId::of::()) + .map(|(_, v)| v)? .downcast_ref::() .cloned() } @@ -364,8 +366,13 @@ impl<'src> ScopeState { while let Some(parent_ptr) = search_parent { // safety: all parent pointers are valid thanks to the bump arena let parent = unsafe { &*parent_ptr }; - if let Some(shared) = parent.shared_contexts.borrow().get(&TypeId::of::()) { - return shared.downcast_ref::().cloned(); + if let Some(shared) = parent + .shared_contexts + .borrow() + .iter() + .find(|(k, _)| *k == TypeId::of::()) + { + return shared.1.downcast_ref::().cloned(); } search_parent = parent.parent; } @@ -398,7 +405,7 @@ impl<'src> ScopeState { self.shared_contexts .borrow_mut() - .insert(TypeId::of::(), Box::new(value)); + .push((TypeId::of::(), Box::new(value))); value2 } From 1489492ec4c920a211d50b27a70830ccf9962711 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 7 Jul 2023 12:18:15 -0700 Subject: [PATCH 2/2] Reuse existing slots in provide context --- packages/core/src/scopes.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index 56ca77608..2b9f32f8d 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -401,13 +401,21 @@ impl<'src> ScopeState { /// } /// ``` pub fn provide_context(&self, value: T) -> T { - let value2 = value.clone(); + let mut contexts = self.shared_contexts.borrow_mut(); - self.shared_contexts - .borrow_mut() - .push((TypeId::of::(), Box::new(value))); + // If the context exists, swap it out for the new value + for ctx in contexts.iter_mut() { + // Swap the ptr directly + if let Some(ctx) = ctx.1.downcast_mut::() { + std::mem::swap(ctx, &mut value.clone()); + return value; + } + } - value2 + // Else, just push it + contexts.push((TypeId::of::(), Box::new(value.clone()))); + + value } /// Pushes the future onto the poll queue to be polled after the component renders.