diff --git a/Cargo.lock b/Cargo.lock index 43d7b1d39fa..89df289f930 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1629,6 +1629,7 @@ dependencies = [ "net_traits", "pixels", "profile_traits", + "rustc-hash 2.1.1", "serde", "servo_config", "servo_malloc_size_of", @@ -5566,6 +5567,7 @@ dependencies = [ "rayon", "resvg", "rusqlite", + "rustc-hash 2.1.1", "rustls", "rustls-pemfile", "rustls-pki-types", diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index aaf898ef1aa..8de83233b27 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -31,6 +31,7 @@ data-url = { workspace = true } devtools_traits = { workspace = true } embedder_traits = { workspace = true } fst = "0.4" +rustc-hash = { workspace = true } futures = { version = "0.3", package = "futures" } futures-core = { version = "0.3.30", default-features = false } futures-util = { version = "0.3.30", default-features = false } diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index d1e5abc0eba..9a15ffa52f7 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -59,6 +59,7 @@ use net_traits::{ }; use profile_traits::mem::{Report, ReportKind}; use profile_traits::path; +use rustc_hash::FxHashMap; use servo_arc::Arc; use servo_url::{Host, ImmutableOrigin, ServoUrl}; use tokio::sync::mpsc::{ @@ -102,7 +103,7 @@ pub struct HttpState { /// or whether a concurrent pending store should be awaited. pub http_cache_state: HttpCacheState, pub auth_cache: RwLock, - pub history_states: RwLock>>, + pub history_states: RwLock>>, pub client: Client, pub override_manager: CertificateErrorOverrideManager, pub embedder_proxy: Mutex, diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs index 94b6eaaa67c..1409b424e54 100644 --- a/components/net/image_cache.rs +++ b/components/net/image_cache.rs @@ -27,6 +27,7 @@ use pixels::{CorsStatus, ImageFrame, ImageMetadata, PixelFormat, RasterImage, lo use profile_traits::mem::{Report, ReportKind}; use profile_traits::path; use resvg::{tiny_skia, usvg}; +use rustc_hash::FxHashMap; use servo_config::pref; use servo_url::{ImmutableOrigin, ServoUrl}; use webrender_api::units::DeviceIntSize; @@ -185,7 +186,7 @@ type ImageKey = (ServoUrl, ImmutableOrigin, Option); struct AllPendingLoads { // The loads, indexed by a load key. Used during most operations, // for performance reasons. - loads: HashMap, + loads: FxHashMap, // Get a load key from its url and requesting origin. Used ony when starting and // finishing a load or when adding a new listener. @@ -198,8 +199,8 @@ struct AllPendingLoads { impl AllPendingLoads { fn new() -> AllPendingLoads { AllPendingLoads { - loads: HashMap::new(), - url_to_load_key: HashMap::new(), + loads: FxHashMap::default(), + url_to_load_key: HashMap::default(), keygen: LoadKeyGenerator::new(), } } diff --git a/components/net/indexeddb/idb_thread.rs b/components/net/indexeddb/idb_thread.rs index 3cea4e948b9..4dae0041039 100644 --- a/components/net/indexeddb/idb_thread.rs +++ b/components/net/indexeddb/idb_thread.rs @@ -14,6 +14,7 @@ use net_traits::indexeddb_thread::{ AsyncOperation, BackendError, BackendResult, CreateObjectResult, DbResult, IndexedDBThreadMsg, IndexedDBTxnMode, KeyPath, SyncOperation, }; +use rustc_hash::FxHashMap; use servo_config::pref; use servo_url::origin::ImmutableOrigin; use uuid::Uuid; @@ -78,7 +79,7 @@ impl IndexedDBDescription { struct IndexedDBEnvironment { engine: E, - transactions: HashMap, + transactions: FxHashMap, serial_number_counter: u64, } @@ -86,7 +87,7 @@ impl IndexedDBEnvironment { fn new(engine: E) -> IndexedDBEnvironment { IndexedDBEnvironment { engine, - transactions: HashMap::new(), + transactions: FxHashMap::default(), serial_number_counter: 0, } } diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index b244ae7d87e..b1810cd36ae 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -42,6 +42,7 @@ use profile_traits::mem::{ }; use profile_traits::path; use profile_traits::time::ProfilerChan; +use rustc_hash::FxHashMap; use rustls::RootCertStore; use serde::{Deserialize, Serialize}; use servo_arc::Arc as ServoArc; @@ -182,8 +183,8 @@ struct ResourceChannelManager { config_dir: Option, ca_certificates: CACertificates, ignore_certificate_errors: bool, - cancellation_listeners: HashMap>, - cookie_listeners: HashMap>, + cancellation_listeners: FxHashMap>, + cookie_listeners: FxHashMap>, } fn create_http_states( @@ -207,7 +208,7 @@ fn create_http_states( hsts_list: RwLock::new(hsts_list), cookie_jar: RwLock::new(cookie_jar), auth_cache: RwLock::new(auth_cache), - history_states: RwLock::new(HashMap::new()), + history_states: RwLock::new(FxHashMap::default()), http_cache: RwLock::new(http_cache), http_cache_state: Mutex::new(HashMap::new()), client: create_http_client(create_tls_config( @@ -224,7 +225,7 @@ fn create_http_states( hsts_list: RwLock::new(HstsList::default()), cookie_jar: RwLock::new(CookieStorage::new(150)), auth_cache: RwLock::new(AuthCache::default()), - history_states: RwLock::new(HashMap::new()), + history_states: RwLock::new(FxHashMap::default()), http_cache: RwLock::new(HttpCache::default()), http_cache_state: Mutex::new(HashMap::new()), client: create_http_client(create_tls_config( diff --git a/components/net/storage_thread.rs b/components/net/storage_thread.rs index 449ffe8b63e..55a77f590b5 100644 --- a/components/net/storage_thread.rs +++ b/components/net/storage_thread.rs @@ -15,6 +15,7 @@ use profile_traits::mem::{ ProcessReports, ProfilerChan as MemProfilerChan, Report, ReportKind, perform_memory_report, }; use profile_traits::path; +use rustc_hash::FxHashMap; use servo_url::ServoUrl; use crate::resource_thread; @@ -52,7 +53,7 @@ type OriginEntry = (usize, BTreeMap); struct StorageManager { port: GenericReceiver, - session_data: HashMap>, + session_data: FxHashMap>, local_data: HashMap, config_dir: Option, } @@ -65,7 +66,7 @@ impl StorageManager { } StorageManager { port, - session_data: HashMap::new(), + session_data: FxHashMap::default(), local_data, config_dir, } diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs index 0c25a560afc..9f12a57092d 100644 --- a/components/net/tests/main.rs +++ b/components/net/tests/main.rs @@ -51,6 +51,7 @@ use net_traits::filemanager_thread::FileTokenCheck; use net_traits::request::Request; use net_traits::response::Response; use net_traits::{AsyncRuntime, FetchTaskTarget, ResourceFetchTiming, ResourceTimingType}; +use rustc_hash::FxHashMap; use rustls_pemfile::{certs, pkcs8_private_keys}; use rustls_pki_types::{CertificateDer, PrivateKeyDer}; use servo_arc::Arc as ServoArc; @@ -146,7 +147,7 @@ fn create_http_state(fc: Option) -> HttpState { hsts_list: RwLock::new(net::hsts::HstsList::default()), cookie_jar: RwLock::new(net::cookie_storage::CookieStorage::new(150)), auth_cache: RwLock::new(net::resource_thread::AuthCache::default()), - history_states: RwLock::new(HashMap::new()), + history_states: RwLock::new(FxHashMap::default()), http_cache: RwLock::new(net::http_cache::HttpCache::default()), http_cache_state: Mutex::new(HashMap::new()), client: create_http_client(create_tls_config( diff --git a/components/script/document_collection.rs b/components/script/document_collection.rs index 511d4ac4a55..12c104cf705 100644 --- a/components/script/document_collection.rs +++ b/components/script/document_collection.rs @@ -2,9 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::{HashMap, hash_map}; +use std::collections::hash_map; use base::id::{BrowsingContextId, PipelineId}; +use rustc_hash::{FxBuildHasher, FxHashMap}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::{Dom, DomRoot}; @@ -20,7 +21,7 @@ use crate::dom::window::Window; #[derive(JSTraceable)] #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] pub(crate) struct DocumentCollection { - map: HashMapTracedValues>, + map: HashMapTracedValues, FxBuildHasher>, } impl DocumentCollection { @@ -95,7 +96,7 @@ impl Default for DocumentCollection { #[cfg_attr(crown, allow(crown::unrooted_must_root))] fn default() -> Self { Self { - map: HashMapTracedValues::new(), + map: HashMapTracedValues::new_fx(), } } } @@ -133,7 +134,7 @@ struct DocumentTreeNode { /// [st]: crate::script_thread::ScriptThread #[derive(Default)] struct DocumentTree { - tree: HashMap, + tree: FxHashMap, } impl DocumentTree { diff --git a/components/script/dom/abstractworkerglobalscope.rs b/components/script/dom/abstractworkerglobalscope.rs index 95a29dcbe71..179efb8a11a 100644 --- a/components/script/dom/abstractworkerglobalscope.rs +++ b/components/script/dom/abstractworkerglobalscope.rs @@ -2,10 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashSet; - use crossbeam_channel::{Receiver, select}; use devtools_traits::DevtoolScriptControlMsg; +use rustc_hash::FxHashSet; use crate::dom::bindings::conversions::DerivedFrom; use crate::dom::bindings::reflector::DomObject; @@ -55,7 +54,7 @@ pub(crate) fn run_worker_event_loop( let event = select! { recv(worker_scope.control_receiver()) -> msg => T::from_control_msg(msg.unwrap()), recv(task_queue.select()) -> msg => { - task_queue.take_tasks(msg.unwrap(), &HashSet::new()); + task_queue.take_tasks(msg.unwrap(), &FxHashSet::default()); T::from_worker_msg(task_queue.recv().unwrap()) }, recv(devtools_receiver) -> msg => T::from_devtools_msg(msg.unwrap()), @@ -74,7 +73,7 @@ pub(crate) fn run_worker_event_loop( while !scope.is_closing() { // Batch all events that are ready. // The task queue will throttle non-priority tasks if necessary. - match task_queue.take_tasks_and_recv(&HashSet::new()) { + match task_queue.take_tasks_and_recv(&FxHashSet::default()) { Err(_) => match devtools_receiver.try_recv() { Ok(message) => sequential.push(T::from_devtools_msg(message)), Err(_) => break, diff --git a/components/script/dom/bindings/serializable.rs b/components/script/dom/bindings/serializable.rs index 6087ce49a7e..4f343584caa 100644 --- a/components/script/dom/bindings/serializable.rs +++ b/components/script/dom/bindings/serializable.rs @@ -5,9 +5,8 @@ //! Trait representing the concept of [serializable objects] //! (). -use std::collections::HashMap; - use base::id::{Index, NamespaceIndex, PipelineNamespaceId}; +use rustc_hash::FxHashMap; use script_bindings::structuredclone::MarkedAsSerializableInIdl; use crate::dom::bindings::reflector::DomObject; @@ -68,7 +67,7 @@ where /// should be used to read/store serialized instances of this type. fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option, Self::Data>>; + ) -> &'a mut Option, Self::Data>>; } pub(crate) fn assert_serializable() {} diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs index cb998a7f808..a48b575227b 100644 --- a/components/script/dom/bindings/structuredclone.rs +++ b/components/script/dom/bindings/structuredclone.rs @@ -4,7 +4,6 @@ //! This module implements structured cloning, as defined by [HTML](https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data). -use std::collections::HashMap; use std::ffi::CStr; use std::os::raw; use std::ptr; @@ -34,6 +33,7 @@ use js::rust::wrappers::{JS_ReadStructuredClone, JS_WriteStructuredClone}; use js::rust::{ CustomAutoRooterGuard, HandleValue, JSAutoStructuredCloneBufferWrapper, MutableHandleValue, }; +use rustc_hash::FxHashMap; use script_bindings::conversions::{IDLInterface, SafeToJSValConvertible}; use strum::IntoEnumIterator; @@ -191,7 +191,7 @@ unsafe fn write_object( ) -> bool { if let Ok((new_id, serialized)) = object.serialize() { let objects = T::serialized_storage(StructuredData::Writer(sc_writer)) - .get_or_insert_with(HashMap::new); + .get_or_insert(FxHashMap::default()); objects.insert(new_id, serialized); let storage_key = StorageKey::new(new_id); @@ -416,8 +416,8 @@ unsafe fn try_transfer( let (id, object) = object.transfer().map_err(OperationError::Exception)?; // 2. Store the transferred object at a given key. - let objects = - T::serialized_storage(StructuredData::Writer(sc_writer)).get_or_insert_with(HashMap::new); + let objects = T::serialized_storage(StructuredData::Writer(sc_writer)) + .get_or_insert(FxHashMap::default()); objects.insert(id, object); let index = id.index.0.get(); @@ -587,32 +587,33 @@ pub(crate) struct StructuredDataReader<'a> { /// A map of port implementations, /// used as part of the "transfer-receiving" steps of ports, /// to produce the DOM ports stored in `message_ports` above. - pub(crate) port_impls: Option>, + pub(crate) port_impls: Option>, /// A map of transform stream implementations, - pub(crate) transform_streams_port_impls: Option>, + pub(crate) transform_streams_port_impls: Option>, /// A map of blob implementations, /// used as part of the "deserialize" steps of blobs, /// to produce the DOM blobs stored in `blobs` above. - pub(crate) blob_impls: Option>, + pub(crate) blob_impls: Option>, /// A map of serialized points. - pub(crate) points: Option>, + pub(crate) points: Option>, /// A map of serialized rects. - pub(crate) rects: Option>, + pub(crate) rects: Option>, /// A map of serialized quads. - pub(crate) quads: Option>, + pub(crate) quads: Option>, /// A map of serialized matrices. - pub(crate) matrices: Option>, + pub(crate) matrices: Option>, /// A map of serialized exceptions. - pub(crate) exceptions: Option>, + pub(crate) exceptions: Option>, /// A map of serialized quota exceeded errors. pub(crate) quota_exceeded_errors: - Option>, + Option>, // A map of serialized image bitmaps. - pub(crate) image_bitmaps: Option>, + pub(crate) image_bitmaps: Option>, /// A map of transferred image bitmaps. - pub(crate) transferred_image_bitmaps: Option>, + pub(crate) transferred_image_bitmaps: Option>, /// A map of transferred offscreen canvases. - pub(crate) offscreen_canvases: Option>, + pub(crate) offscreen_canvases: + Option>, } /// A data holder for transferred and serialized objects. @@ -622,30 +623,31 @@ pub(crate) struct StructuredDataWriter { /// Error record. pub(crate) error: Option, /// Transferred ports. - pub(crate) ports: Option>, + pub(crate) ports: Option>, /// Transferred transform streams. - pub(crate) transform_streams_port: Option>, + pub(crate) transform_streams_port: Option>, /// Serialized points. - pub(crate) points: Option>, + pub(crate) points: Option>, /// Serialized rects. - pub(crate) rects: Option>, + pub(crate) rects: Option>, /// Serialized quads. - pub(crate) quads: Option>, + pub(crate) quads: Option>, /// Serialized matrices. - pub(crate) matrices: Option>, + pub(crate) matrices: Option>, /// Serialized exceptions. - pub(crate) exceptions: Option>, + pub(crate) exceptions: Option>, /// Serialized quota exceeded errors. pub(crate) quota_exceeded_errors: - Option>, + Option>, /// Serialized blobs. - pub(crate) blobs: Option>, + pub(crate) blobs: Option>, /// Serialized image bitmaps. - pub(crate) image_bitmaps: Option>, + pub(crate) image_bitmaps: Option>, /// Transferred image bitmaps. - pub(crate) transferred_image_bitmaps: Option>, + pub(crate) transferred_image_bitmaps: Option>, /// Transferred offscreen canvases. - pub(crate) offscreen_canvases: Option>, + pub(crate) offscreen_canvases: + Option>, } /// Writes a structured clone. Returns a `DataClone` error if that fails. diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index e30a9611877..67c546520f8 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -40,6 +40,7 @@ use js::glue::{CallScriptTracer, CallStringTracer, CallValueTracer}; use js::jsapi::{GCTraceKindToAscii, Heap, JSScript, JSString, JSTracer, TraceKind}; use js::jsval::JSVal; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; +use rustc_hash::FxBuildHasher; pub(crate) use script_bindings::trace::*; use crate::dom::bindings::cell::DomRefCell; @@ -92,6 +93,9 @@ impl MallocSizeOf for NoTrace { /// HashMap wrapper, that has non-jsmanaged keys /// /// Not all methods are reexposed, but you can access inner type via .0 +/// If you need cryptographic secure hashs, or your keys are arbitrary large inputs +/// stick with the default hasher. Otherwise, stronlgy think about using FxHashBuilder +/// with `new_fx()` #[cfg_attr(crown, crown::trace_in_no_trace_lint::must_not_have_traceable(0))] #[derive(Clone, Debug)] pub(crate) struct HashMapTracedValues(pub(crate) HashMap); @@ -111,6 +115,14 @@ impl HashMapTracedValues { } } +impl HashMapTracedValues { + #[inline] + #[must_use] + pub(crate) fn new_fx() -> HashMapTracedValues { + Self(HashMap::with_hasher(FxBuildHasher)) + } +} + impl HashMapTracedValues { #[inline] pub(crate) fn iter(&self) -> std::collections::hash_map::Iter<'_, K, V> { diff --git a/components/script/dom/bindings/transferable.rs b/components/script/dom/bindings/transferable.rs index 620c4f6a4d4..01e7eee7aa0 100644 --- a/components/script/dom/bindings/transferable.rs +++ b/components/script/dom/bindings/transferable.rs @@ -5,10 +5,10 @@ //! Trait representing the concept of [transferable objects] //! (). -use std::collections::HashMap; use std::hash::Hash; use base::id::NamespaceIndex; +use rustc_hash::FxHashMap; use script_bindings::structuredclone::MarkedAsTransferableInIdl; use crate::dom::bindings::error::Fallible; @@ -40,7 +40,7 @@ where fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option, Self::Data>>; + ) -> &'a mut Option, Self::Data>>; } pub(crate) fn assert_transferable() {} diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index 18e968aaa70..6c6c8d66b02 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; use std::ptr; use std::rc::Rc; @@ -14,6 +13,7 @@ use js::jsapi::JSObject; use js::rust::HandleObject; use js::typedarray::{ArrayBufferU8, Uint8}; use net_traits::filemanager_thread::RelativePos; +use rustc_hash::FxHashMap; use uuid::Uuid; use crate::dom::bindings::buffer_source::create_buffer_source; @@ -120,7 +120,7 @@ impl Serializable for Blob { fn serialized_storage<'a>( reader: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match reader { StructuredData::Reader(r) => &mut r.blob_impls, StructuredData::Writer(w) => &mut w.blobs, diff --git a/components/script/dom/canvas/imagebitmap.rs b/components/script/dom/canvas/imagebitmap.rs index 8a65e092bc3..461512d22e2 100644 --- a/components/script/dom/canvas/imagebitmap.rs +++ b/components/script/dom/canvas/imagebitmap.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::{Cell, Ref}; -use std::collections::HashMap; use std::rc::Rc; use base::id::{ImageBitmapId, ImageBitmapIndex}; @@ -11,6 +10,7 @@ use constellation_traits::SerializableImageBitmap; use dom_struct::dom_struct; use euclid::default::{Point2D, Rect, Size2D}; use pixels::{CorsStatus, PixelFormat, Snapshot, SnapshotAlphaMode, SnapshotPixelFormat}; +use rustc_hash::FxHashMap; use script_bindings::error::{Error, Fallible}; use script_bindings::realms::{AlreadyInRealm, InRealm}; @@ -663,7 +663,7 @@ impl Serializable for ImageBitmap { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.image_bitmaps, StructuredData::Writer(w) => &mut w.image_bitmaps, @@ -716,7 +716,7 @@ impl Transferable for ImageBitmap { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.transferred_image_bitmaps, StructuredData::Writer(w) => &mut w.transferred_image_bitmaps, diff --git a/components/script/dom/canvas/offscreencanvas.rs b/components/script/dom/canvas/offscreencanvas.rs index f95f173ebbe..1f584484622 100644 --- a/components/script/dom/canvas/offscreencanvas.rs +++ b/components/script/dom/canvas/offscreencanvas.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::Cell; -use std::collections::HashMap; use std::rc::Rc; use base::id::{OffscreenCanvasId, OffscreenCanvasIndex}; @@ -12,6 +11,7 @@ use dom_struct::dom_struct; use euclid::default::Size2D; use js::rust::{HandleObject, HandleValue}; use pixels::{EncodedImageType, Snapshot}; +use rustc_hash::FxHashMap; use script_bindings::weakref::WeakRef; use crate::canvas_context::{CanvasContext, OffscreenRenderingContext}; @@ -261,7 +261,7 @@ impl Transferable for OffscreenCanvas { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.offscreen_canvases, StructuredData::Writer(w) => &mut w.offscreen_canvases, diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index dbe8885176a..0db9949b727 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -47,6 +47,7 @@ use percent_encoding::percent_decode; use profile_traits::ipc as profile_ipc; use profile_traits::time::TimerMetadataFrameType; use regex::bytes::Regex; +use rustc_hash::FxBuildHasher; use script_bindings::codegen::GenericBindings::ElementBinding::ElementMethods; use script_bindings::interfaces::DocumentHelpers; use script_bindings::script_runtime::JSContext; @@ -474,15 +475,17 @@ pub(crate) struct Document { /// hosting the media controls UI. media_controls: DomRefCell>>, /// List of all context 2d IDs that need flushing. - dirty_2d_contexts: DomRefCell>>, + dirty_2d_contexts: + DomRefCell, FxBuildHasher>>, /// List of all WebGL context IDs that need flushing. dirty_webgl_contexts: - DomRefCell>>, + DomRefCell, FxBuildHasher>>, /// Whether or not animated images need to have their contents updated. has_pending_animated_image_update: Cell, /// List of all WebGPU contexts that need flushing. #[cfg(feature = "webgpu")] - dirty_webgpu_contexts: DomRefCell>>, + dirty_webgpu_contexts: + DomRefCell, FxBuildHasher>>, /// selection: MutNullableDom, /// A timeline for animations which is used for synchronizing animations. @@ -3418,11 +3421,11 @@ impl Document { shadow_roots: DomRefCell::new(HashSet::new()), shadow_roots_styles_changed: Cell::new(false), media_controls: DomRefCell::new(HashMap::new()), - dirty_2d_contexts: DomRefCell::new(HashMapTracedValues::new()), - dirty_webgl_contexts: DomRefCell::new(HashMapTracedValues::new()), + dirty_2d_contexts: DomRefCell::new(HashMapTracedValues::new_fx()), + dirty_webgl_contexts: DomRefCell::new(HashMapTracedValues::new_fx()), has_pending_animated_image_update: Cell::new(false), #[cfg(feature = "webgpu")] - dirty_webgpu_contexts: DomRefCell::new(HashMapTracedValues::new()), + dirty_webgpu_contexts: DomRefCell::new(HashMapTracedValues::new_fx()), selection: MutNullableDom::new(None), animation_timeline: if pref!(layout_animations_test_enabled) { DomRefCell::new(AnimationTimeline::new_for_testing()) diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs index 9309cabe75f..cdf5ec957ee 100644 --- a/components/script/dom/domexception.rs +++ b/components/script/dom/domexception.rs @@ -2,12 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; - use base::id::{DomExceptionId, DomExceptionIndex}; use constellation_traits::DomException; use dom_struct::dom_struct; use js::rust::HandleObject; +use rustc_hash::FxHashMap; use crate::dom::bindings::codegen::Bindings::DOMExceptionBinding::{ DOMExceptionConstants, DOMExceptionMethods, @@ -280,7 +279,7 @@ impl Serializable for DOMException { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.exceptions, StructuredData::Writer(writer) => &mut writer.exceptions, diff --git a/components/script/dom/dommatrix.rs b/components/script/dom/dommatrix.rs index cf726eeb123..16204f668c2 100644 --- a/components/script/dom/dommatrix.rs +++ b/components/script/dom/dommatrix.rs @@ -2,14 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; - use base::id::{DomMatrixId, DomMatrixIndex}; use constellation_traits::DomMatrix; use dom_struct::dom_struct; use euclid::default::Transform3D; use js::rust::{CustomAutoRooterGuard, HandleObject}; use js::typedarray::{Float32Array, Float64Array}; +use rustc_hash::FxHashMap; use script_bindings::str::DOMString; use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::{DOMMatrixInit, DOMMatrixMethods}; @@ -574,7 +573,7 @@ impl Serializable for DOMMatrix { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.matrices, StructuredData::Writer(writer) => &mut writer.matrices, diff --git a/components/script/dom/dommatrixreadonly.rs b/components/script/dom/dommatrixreadonly.rs index e5f092df2f0..9d498193b19 100644 --- a/components/script/dom/dommatrixreadonly.rs +++ b/components/script/dom/dommatrixreadonly.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::Cell; -use std::collections::HashMap; use std::{f64, ptr}; use base::id::{DomMatrixId, DomMatrixIndex}; @@ -17,6 +16,7 @@ use js::jsapi::JSObject; use js::jsval; use js::rust::{CustomAutoRooterGuard, HandleObject, ToString}; use js::typedarray::{Float32Array, Float64Array}; +use rustc_hash::FxHashMap; use style::parser::ParserContext; use url::Url; @@ -1033,7 +1033,7 @@ impl Serializable for DOMMatrixReadOnly { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.matrices, StructuredData::Writer(writer) => &mut writer.matrices, diff --git a/components/script/dom/dompoint.rs b/components/script/dom/dompoint.rs index 5e848c43c47..8cf388b4a2b 100644 --- a/components/script/dom/dompoint.rs +++ b/components/script/dom/dompoint.rs @@ -2,12 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; - use base::id::{DomPointId, DomPointIndex}; use constellation_traits::DomPoint; use dom_struct::dom_struct; use js::rust::HandleObject; +use rustc_hash::FxHashMap; use crate::dom::bindings::codegen::Bindings::DOMPointBinding::{DOMPointInit, DOMPointMethods}; use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointReadOnlyMethods; @@ -165,7 +164,7 @@ impl Serializable for DOMPoint { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.points, StructuredData::Writer(writer) => &mut writer.points, diff --git a/components/script/dom/dompointreadonly.rs b/components/script/dom/dompointreadonly.rs index 4d1faec3ccd..c6f0f6a9463 100644 --- a/components/script/dom/dompointreadonly.rs +++ b/components/script/dom/dompointreadonly.rs @@ -3,12 +3,12 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::Cell; -use std::collections::HashMap; use base::id::{DomPointId, DomPointIndex}; use constellation_traits::DomPoint; use dom_struct::dom_struct; use js::rust::HandleObject; +use rustc_hash::FxHashMap; use crate::dom::bindings::codegen::Bindings::DOMMatrixBinding::DOMMatrixInit; use crate::dom::bindings::codegen::Bindings::DOMPointBinding::DOMPointInit; @@ -213,7 +213,7 @@ impl Serializable for DOMPointReadOnly { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.points, StructuredData::Writer(w) => &mut w.points, diff --git a/components/script/dom/domquad.rs b/components/script/dom/domquad.rs index 44b21d9f4cc..25a1944bf35 100644 --- a/components/script/dom/domquad.rs +++ b/components/script/dom/domquad.rs @@ -2,12 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; - use base::id::{DomQuadId, DomQuadIndex}; use constellation_traits::{DomPoint, DomQuad}; use dom_struct::dom_struct; use js::rust::HandleObject; +use rustc_hash::FxHashMap; use crate::dom::bindings::codegen::Bindings::DOMPointBinding::{DOMPointInit, DOMPointMethods}; use crate::dom::bindings::codegen::Bindings::DOMQuadBinding::{DOMQuadInit, DOMQuadMethods}; @@ -255,7 +254,7 @@ impl Serializable for DOMQuad { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.quads, StructuredData::Writer(writer) => &mut writer.quads, diff --git a/components/script/dom/domrect.rs b/components/script/dom/domrect.rs index 705e40d448b..9b9c973a20a 100644 --- a/components/script/dom/domrect.rs +++ b/components/script/dom/domrect.rs @@ -2,12 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; - use base::id::{DomRectId, DomRectIndex}; use constellation_traits::DomRect; use dom_struct::dom_struct; use js::rust::HandleObject; +use rustc_hash::FxHashMap; use crate::dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods; use crate::dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::{ @@ -162,7 +161,7 @@ impl Serializable for DOMRect { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.rects, StructuredData::Writer(writer) => &mut writer.rects, diff --git a/components/script/dom/domrectreadonly.rs b/components/script/dom/domrectreadonly.rs index df7fab4faf4..1d6b7d12112 100644 --- a/components/script/dom/domrectreadonly.rs +++ b/components/script/dom/domrectreadonly.rs @@ -3,12 +3,12 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::Cell; -use std::collections::HashMap; use base::id::{DomRectId, DomRectIndex}; use constellation_traits::DomRect; use dom_struct::dom_struct; use js::rust::HandleObject; +use rustc_hash::FxHashMap; use crate::dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::{ DOMRectInit, DOMRectReadOnlyMethods, @@ -239,7 +239,7 @@ impl Serializable for DOMRectReadOnly { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.rects, StructuredData::Writer(writer) => &mut writer.rects, diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index e4c3842385a..26a67867873 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -57,6 +57,7 @@ use net_traits::{ ResourceThreads, fetch_async, }; use profile_traits::{ipc as profile_ipc, mem as profile_mem, time as profile_time}; +use rustc_hash::{FxBuildHasher, FxHashMap}; use script_bindings::interfaces::GlobalScopeHelpers; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use timers::{TimerEventRequest, TimerId}; @@ -204,18 +205,22 @@ pub(crate) struct GlobalScope { broadcast_channel_state: DomRefCell, /// The blobs managed by this global, if any. - blob_state: DomRefCell>, + blob_state: DomRefCell>, /// registration_map: DomRefCell< - HashMapTracedValues>, + HashMapTracedValues< + ServiceWorkerRegistrationId, + Dom, + FxBuildHasher, + >, >, /// cookie_store: MutNullableDom, /// - worker_map: DomRefCell>>, + worker_map: DomRefCell, FxBuildHasher>>, /// Pipeline id associated with this global. #[no_trace] @@ -234,7 +239,7 @@ pub(crate) struct GlobalScope { module_map: DomRefCell>>, #[ignore_malloc_size_of = "mozjs"] - inline_module_map: DomRefCell>>, + inline_module_map: DomRefCell>>, /// For providing instructions to an optional devtools server. #[no_trace] @@ -336,7 +341,7 @@ pub(crate) struct GlobalScope { /// WebGPU devices #[cfg(feature = "webgpu")] - gpu_devices: DomRefCell>>, + gpu_devices: DomRefCell, FxBuildHasher>>, // https://w3c.github.io/performance-timeline/#supportedentrytypes-attribute #[ignore_malloc_size_of = "mozjs"] @@ -510,7 +515,7 @@ pub(crate) enum MessagePortState { /// The message-port router id for this global, and a map of managed ports. Managed( #[no_trace] MessagePortRouterId, - HashMapTracedValues, + HashMapTracedValues, ), /// This global is not managing any ports at this time. UnManaged, @@ -765,9 +770,9 @@ impl GlobalScope { blob_state: Default::default(), eventtarget: EventTarget::new_inherited(), crypto: Default::default(), - registration_map: DomRefCell::new(HashMapTracedValues::new()), + registration_map: DomRefCell::new(HashMapTracedValues::new_fx()), cookie_store: Default::default(), - worker_map: DomRefCell::new(HashMapTracedValues::new()), + worker_map: DomRefCell::new(HashMapTracedValues::new_fx()), pipeline_id, devtools_wants_updates: Default::default(), console_timers: DomRefCell::new(Default::default()), @@ -793,7 +798,7 @@ impl GlobalScope { #[cfg(feature = "webgpu")] gpu_id_hub, #[cfg(feature = "webgpu")] - gpu_devices: DomRefCell::new(HashMapTracedValues::new()), + gpu_devices: DomRefCell::new(HashMapTracedValues::new_fx()), frozen_supported_performance_entry_types: CachedFrozenArray::new(), https_state: Cell::new(HttpsState::None), console_group_stack: DomRefCell::new(Vec::new()), @@ -1703,7 +1708,7 @@ impl GlobalScope { }), ); let router_id = MessagePortRouterId::new(); - *current_state = MessagePortState::Managed(router_id, HashMapTracedValues::new()); + *current_state = MessagePortState::Managed(router_id, HashMapTracedValues::new_fx()); let _ = self.script_to_constellation_chan().send( ScriptToConstellationMessage::NewMessagePortRouter(router_id, port_control_sender), ); @@ -2373,7 +2378,7 @@ impl GlobalScope { .insert(script_id, Rc::new(module)); } - pub(crate) fn get_inline_module_map(&self) -> &DomRefCell>> { + pub(crate) fn get_inline_module_map(&self) -> &DomRefCell>> { &self.inline_module_map } diff --git a/components/script/dom/html/htmlcanvaselement.rs b/components/script/dom/html/htmlcanvaselement.rs index 1f932078eb4..5cd55c92104 100644 --- a/components/script/dom/html/htmlcanvaselement.rs +++ b/components/script/dom/html/htmlcanvaselement.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::{Cell, RefCell}; -use std::collections::HashMap; use std::rc::Rc; use canvas_traits::webgl::{GLContextAttributes, WebGLVersion}; @@ -19,6 +18,7 @@ use js::error::throw_type_error; use js::rust::{HandleObject, HandleValue}; use layout_api::HTMLCanvasData; use pixels::{EncodedImageType, Snapshot}; +use rustc_hash::FxHashMap; use script_bindings::weakref::WeakRef; use servo_media::streams::MediaStreamType; use servo_media::streams::registry::MediaStreamId; @@ -77,7 +77,7 @@ pub(crate) struct HTMLCanvasElement { // This id and hashmap are used to keep track of ongoing toBlob() calls. callback_id: Cell, #[ignore_malloc_size_of = "not implemented for webidl callbacks"] - blob_callbacks: RefCell>>, + blob_callbacks: RefCell>>, } impl HTMLCanvasElement { @@ -90,7 +90,7 @@ impl HTMLCanvasElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document), context_mode: DomRefCell::new(None), callback_id: Cell::new(0), - blob_callbacks: RefCell::new(HashMap::new()), + blob_callbacks: RefCell::new(FxHashMap::default()), } } diff --git a/components/script/dom/mediasession.rs b/components/script/dom/mediasession.rs index dae35772b48..c1f5a128da2 100644 --- a/components/script/dom/mediasession.rs +++ b/components/script/dom/mediasession.rs @@ -9,6 +9,7 @@ use dom_struct::dom_struct; use embedder_traits::{ MediaMetadata as EmbedderMediaMetadata, MediaSessionActionType, MediaSessionEvent, }; +use rustc_hash::FxBuildHasher; use super::bindings::trace::HashMapTracedValues; use crate::conversions::Convert; @@ -44,8 +45,9 @@ pub(crate) struct MediaSession { playback_state: DomRefCell, /// #[ignore_malloc_size_of = "Rc"] - action_handlers: - DomRefCell>>, + action_handlers: DomRefCell< + HashMapTracedValues, FxBuildHasher>, + >, /// The media instance controlled by this media session. /// For now only HTMLMediaElements are controlled by media sessions. media_instance: MutNullableDom, @@ -58,7 +60,7 @@ impl MediaSession { reflector_: Reflector::new(), metadata: DomRefCell::new(None), playback_state: DomRefCell::new(MediaSessionPlaybackState::None), - action_handlers: DomRefCell::new(HashMapTracedValues::new()), + action_handlers: DomRefCell::new(HashMapTracedValues::new_fx()), media_instance: Default::default(), } } diff --git a/components/script/dom/messageport.rs b/components/script/dom/messageport.rs index f0497c5a8c5..b8507ec2ce8 100644 --- a/components/script/dom/messageport.rs +++ b/components/script/dom/messageport.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use std::cell::{Cell, RefCell}; -use std::collections::HashMap; use std::ptr; use std::rc::Rc; @@ -13,6 +12,7 @@ use dom_struct::dom_struct; use js::jsapi::{Heap, JS_NewObject, JSObject}; use js::jsval::UndefinedValue; use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue}; +use rustc_hash::FxHashMap; use script_bindings::conversions::SafeToJSValConvertible; use crate::dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; @@ -280,7 +280,7 @@ impl Transferable for MessagePort { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.port_impls, StructuredData::Writer(w) => &mut w.ports, diff --git a/components/script/dom/quotaexceedederror.rs b/components/script/dom/quotaexceedederror.rs index 0b75c7aef1d..f453fb9fce5 100644 --- a/components/script/dom/quotaexceedederror.rs +++ b/components/script/dom/quotaexceedederror.rs @@ -2,12 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; - use base::id::{QuotaExceededErrorId, QuotaExceededErrorIndex}; use constellation_traits::SerializableQuotaExceededError; use dom_struct::dom_struct; use js::gc::HandleObject; +use rustc_hash::FxHashMap; use script_bindings::codegen::GenericBindings::QuotaExceededErrorBinding::{ QuotaExceededErrorMethods, QuotaExceededErrorOptions, }; @@ -165,7 +164,7 @@ impl Serializable for QuotaExceededError { /// fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(reader) => &mut reader.quota_exceeded_errors, StructuredData::Writer(writer) => &mut writer.quota_exceeded_errors, diff --git a/components/script/dom/readablestream.rs b/components/script/dom/readablestream.rs index b68e3de63c5..13f828bd77e 100644 --- a/components/script/dom/readablestream.rs +++ b/components/script/dom/readablestream.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use std::cell::{Cell, RefCell}; -use std::collections::HashMap; use std::collections::VecDeque; use std::ptr::{self}; use std::rc::Rc; @@ -11,6 +10,7 @@ use std::rc::Rc; use base::id::{MessagePortId, MessagePortIndex}; use constellation_traits::MessagePortImpl; use dom_struct::dom_struct; +use rustc_hash::FxHashMap; use ipc_channel::ipc::IpcSharedMemory; use js::jsapi::{Heap, JSObject}; use js::jsval::{JSVal, ObjectValue, UndefinedValue}; @@ -2434,7 +2434,7 @@ impl Transferable for ReadableStream { /// Note: we are relying on the port transfer, so the data returned here are related to the port. fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.port_impls, StructuredData::Writer(w) => &mut w.ports, diff --git a/components/script/dom/servoparser/async_html.rs b/components/script/dom/servoparser/async_html.rs index 0959cbbde07..4a83ac95eef 100644 --- a/components/script/dom/servoparser/async_html.rs +++ b/components/script/dom/servoparser/async_html.rs @@ -21,6 +21,7 @@ use html5ever::tree_builder::{ }; use html5ever::{Attribute as HtmlAttribute, ExpandedName, QualName, local_name, ns}; use markup5ever::TokenizerResult; +use rustc_hash::FxHashMap; use servo_url::ServoUrl; use style::context::QuirksMode as ServoQuirksMode; @@ -697,7 +698,7 @@ struct ParseNodeData { pub(crate) struct Sink { current_line: Cell, - parse_node_data: RefCell>, + parse_node_data: RefCell>, next_parse_node_id: Cell, document_node: ParseNode, sender: Sender, @@ -708,7 +709,7 @@ impl Sink { fn new(sender: Sender, allow_declarative_shadow_roots: bool) -> Sink { let sink = Sink { current_line: Cell::new(1), - parse_node_data: RefCell::new(HashMap::new()), + parse_node_data: RefCell::new(FxHashMap::default()), next_parse_node_id: Cell::new(1), document_node: ParseNode { id: 0, diff --git a/components/script/dom/transformstream.rs b/components/script/dom/transformstream.rs index 6fc79bf5d75..bc17c53a069 100644 --- a/components/script/dom/transformstream.rs +++ b/components/script/dom/transformstream.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::Cell; -use std::collections::HashMap; use std::ptr::{self}; use std::rc::Rc; @@ -13,6 +12,7 @@ use dom_struct::dom_struct; use js::jsapi::{Heap, IsPromiseObject, JSObject}; use js::jsval::{JSVal, ObjectValue, UndefinedValue}; use js::rust::{HandleObject as SafeHandleObject, HandleValue as SafeHandleValue, IntoHandle}; +use rustc_hash::FxHashMap; use script_bindings::callback::ExceptionHandling; use script_bindings::realms::InRealm; @@ -1193,7 +1193,7 @@ impl Transferable for TransformStream { fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.transform_streams_port_impls, StructuredData::Writer(w) => &mut w.transform_streams_port, diff --git a/components/script/dom/webrtc/rtcpeerconnection.rs b/components/script/dom/webrtc/rtcpeerconnection.rs index 37ae21a910d..397dc21328e 100644 --- a/components/script/dom/webrtc/rtcpeerconnection.rs +++ b/components/script/dom/webrtc/rtcpeerconnection.rs @@ -3,11 +3,11 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::Cell; -use std::collections::HashMap; use std::rc::Rc; use dom_struct::dom_struct; use js::rust::HandleObject; +use rustc_hash::FxHashMap; use servo_media::ServoMedia; use servo_media::streams::MediaStreamType; use servo_media::streams::registry::MediaStreamId; @@ -73,7 +73,7 @@ pub(crate) struct RTCPeerConnection { ice_connection_state: Cell, signaling_state: Cell, #[ignore_malloc_size_of = "defined in servo-media"] - data_channels: DomRefCell>>, + data_channels: DomRefCell>>, } struct RTCSignaller { @@ -171,7 +171,7 @@ impl RTCPeerConnection { gathering_state: Cell::new(RTCIceGatheringState::New), ice_connection_state: Cell::new(RTCIceConnectionState::New), signaling_state: Cell::new(RTCSignalingState::Stable), - data_channels: DomRefCell::new(HashMap::new()), + data_channels: DomRefCell::new(FxHashMap::default()), } } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 5b19243bd29..6745f19a88a 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -72,6 +72,7 @@ use num_traits::ToPrimitive; use profile_traits::generic_channel as ProfiledGenericChannel; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; +use rustc_hash::{FxBuildHasher, FxHashMap}; use script_bindings::codegen::GenericBindings::WindowBinding::ScrollToOptions; use script_bindings::conversions::SafeToJSValConvertible; use script_bindings::interfaces::WindowHelpers; @@ -366,20 +367,22 @@ pub(crate) struct Window { /// `ImageCache` it adds an entry to this list. When those loads are triggered from /// layout, they also add an etry to [`Self::pending_layout_images`]. #[no_trace] - pending_image_callbacks: DomRefCell>>, + pending_image_callbacks: DomRefCell>>, /// All of the elements that have an outstanding image request that was /// initiated by layout during a reflow. They are stored in the [`ScriptThread`] /// to ensure that the element can be marked dirty when the image data becomes /// available at some point in the future. - pending_layout_images: - DomRefCell>>, + pending_layout_images: DomRefCell< + HashMapTracedValues, FxBuildHasher>, + >, /// Vector images for which layout has intiated rasterization at a specific size /// and whose results are not yet available. They are stored in the [`ScriptThread`] /// so that the element can be marked dirty once the rasterization is completed. - pending_images_for_rasterization: - DomRefCell>>>, + pending_images_for_rasterization: DomRefCell< + HashMapTracedValues>, FxBuildHasher>, + >, /// Directory to store unminified css for this window if unminify-css /// opt is enabled. diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs index 74d3ef1bd13..ba3fd866a9f 100644 --- a/components/script/dom/worklet.rs +++ b/components/script/dom/worklet.rs @@ -12,7 +12,7 @@ use std::cell::OnceCell; use std::cmp::max; -use std::collections::{HashMap, hash_map}; +use std::collections::hash_map; use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicIsize, Ordering}; @@ -25,6 +25,7 @@ use js::jsapi::{GCReason, JS_GC, JS_GetGCParameter, JSGCParamKey, JSTracer}; use malloc_size_of::malloc_size_of_is_0; use net_traits::IpcSend; use net_traits::request::{Destination, RequestBuilder, RequestMode}; +use rustc_hash::FxHashMap; use servo_url::{ImmutableOrigin, ServoUrl}; use style::thread_state::{self, ThreadState}; use swapper::{Swapper, swapper}; @@ -458,7 +459,7 @@ struct WorkletThread { global_init: WorkletGlobalScopeInit, /// The global scopes created by this thread - global_scopes: HashMap>, + global_scopes: FxHashMap>, /// A one-place buffer for control messages control_buffer: Option, @@ -502,7 +503,7 @@ impl WorkletThread { hot_backup_sender: init.hot_backup_sender, cold_backup_sender: init.cold_backup_sender, global_init: init.global_init, - global_scopes: HashMap::new(), + global_scopes: FxHashMap::default(), control_buffer: None, runtime: Runtime::new(None), should_gc: false, diff --git a/components/script/dom/writablestream.rs b/components/script/dom/writablestream.rs index 5592cc500d7..d57da8ab9b4 100644 --- a/components/script/dom/writablestream.rs +++ b/components/script/dom/writablestream.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::cell::{Cell, RefCell}; -use std::collections::{HashMap, VecDeque}; +use std::collections::VecDeque; use std::mem; use std::ptr::{self}; use std::rc::Rc; @@ -17,6 +17,7 @@ use js::rust::{ HandleObject as SafeHandleObject, HandleValue as SafeHandleValue, MutableHandleValue as SafeMutableHandleValue, }; +use rustc_hash::FxHashMap; use script_bindings::codegen::GenericBindings::MessagePortBinding::MessagePortMethods; use script_bindings::conversions::SafeToJSValConvertible; @@ -1293,7 +1294,7 @@ impl Transferable for WritableStream { /// Note: we are relying on the port transfer, so the data returned here are related to the port. fn serialized_storage<'a>( data: StructuredData<'a, '_>, - ) -> &'a mut Option> { + ) -> &'a mut Option> { match data { StructuredData::Reader(r) => &mut r.port_impls, StructuredData::Writer(w) => &mut w.ports, diff --git a/components/script/messaging.rs b/components/script/messaging.rs index d9f6d2f285b..30449252e7c 100644 --- a/components/script/messaging.rs +++ b/components/script/messaging.rs @@ -5,7 +5,6 @@ use core::fmt; #[cfg(feature = "webgpu")] use std::cell::RefCell; -use std::collections::HashSet; use std::option::Option; use std::result::Result; @@ -22,6 +21,7 @@ use net_traits::FetchResponseMsg; use net_traits::image_cache::ImageCacheResponseMessage; use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan}; use profile_traits::time::{self as profile_time}; +use rustc_hash::FxHashSet; use script_traits::{Painter, ScriptThreadMessage}; use stylo_atoms::Atom; use timers::TimerScheduler; @@ -403,7 +403,7 @@ impl ScriptThreadReceivers { &self, task_queue: &TaskQueue, timer_scheduler: &TimerScheduler, - fully_active: &HashSet, + fully_active: &FxHashSet, ) -> MixedMessage { select! { recv(task_queue.select()) -> msg => { @@ -444,7 +444,7 @@ impl ScriptThreadReceivers { pub(crate) fn try_recv( &self, task_queue: &TaskQueue, - fully_active: &HashSet, + fully_active: &FxHashSet, ) -> Option { if let Ok(message) = self.constellation_receiver.try_recv() { let message = message diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 39a596bea71..b66f4c1aaa4 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -18,7 +18,7 @@ //! loop. use std::cell::{Cell, RefCell}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::default::Default; use std::option::Option; use std::rc::Rc; @@ -83,6 +83,7 @@ use percent_encoding::percent_decode; use profile_traits::mem::{ProcessReports, ReportsChan, perform_memory_report}; use profile_traits::time::ProfilerCategory; use profile_traits::time_profile; +use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; use script_traits::{ ConstellationInputEvent, DiscardBrowsingContext, DocumentActivity, InitialScriptState, NewLayoutInfo, Painter, ProgressiveWebMetricType, ScriptThreadMessage, UpdatePipelineIdReason, @@ -204,7 +205,8 @@ pub struct ScriptThread { documents: DomRefCell, /// The window proxies known by this thread /// TODO: this map grows, but never shrinks. Issue #15258. - window_proxies: DomRefCell>>, + window_proxies: + DomRefCell, FxBuildHasher>>, /// A list of data pertaining to loads that have not yet received a network response incomplete_loads: DomRefCell>, /// A vector containing parser contexts which have not yet been fully processed @@ -249,7 +251,7 @@ pub struct ScriptThread { /// List of pipelines that have been owned and closed by this script thread. #[no_trace] - closed_pipelines: DomRefCell>, + closed_pipelines: DomRefCell>, /// microtask_queue: Rc, @@ -311,7 +313,7 @@ pub struct ScriptThread { /// A map from pipelines to all owned nodes ever created in this script thread #[no_trace] - pipeline_to_node_ids: DomRefCell>, + pipeline_to_node_ids: DomRefCell>, /// Code is running as a consequence of a user interaction is_user_interacting: Cell, @@ -726,7 +728,7 @@ impl ScriptThread { with_script_thread(|script_thread| script_thread.is_user_interacting.get()) } - pub(crate) fn get_fully_active_document_ids(&self) -> HashSet { + pub(crate) fn get_fully_active_document_ids(&self) -> FxHashSet { self.documents .borrow() .iter() @@ -737,7 +739,7 @@ impl ScriptThread { None } }) - .fold(HashSet::new(), |mut set, id| { + .fold(FxHashSet::default(), |mut set, id| { let _ = set.insert(id); set }) @@ -983,7 +985,7 @@ impl ScriptThread { ScriptThread { documents: DomRefCell::new(DocumentCollection::default()), last_render_opportunity_time: Default::default(), - window_proxies: DomRefCell::new(HashMapTracedValues::new()), + window_proxies: DomRefCell::new(HashMapTracedValues::new_fx()), incomplete_loads: DomRefCell::new(vec![]), incomplete_parser_contexts: IncompleteParserContexts(RefCell::new(vec![])), senders, @@ -996,7 +998,7 @@ impl ScriptThread { timer_scheduler: Default::default(), microtask_queue, js_runtime, - closed_pipelines: DomRefCell::new(HashSet::new()), + closed_pipelines: DomRefCell::new(FxHashSet::default()), mutation_observer_microtask_queued: Default::default(), mutation_observers: Default::default(), signal_slots: Default::default(), diff --git a/components/script/task_manager.rs b/components/script/task_manager.rs index 36601efc2c3..b4da5078920 100644 --- a/components/script/task_manager.rs +++ b/components/script/task_manager.rs @@ -5,9 +5,9 @@ use core::cell::RefCell; use core::sync::atomic::Ordering; use std::cell::Ref; -use std::collections::HashMap; use base::id::PipelineId; +use rustc_hash::FxHashMap; use strum::VariantArray; use crate::messaging::ScriptEventLoopSender; @@ -20,7 +20,7 @@ enum TaskCancellers { /// of them need to have the same canceller flag for all task sources. Shared(TaskCanceller), /// For `Window` each `TaskSource` has its own canceller. - OnePerTaskSource(RefCell>), + OnePerTaskSource(RefCell>), } impl TaskCancellers { diff --git a/components/script/task_queue.rs b/components/script/task_queue.rs index 0becbe33829..4d49c229713 100644 --- a/components/script/task_queue.rs +++ b/components/script/task_queue.rs @@ -5,11 +5,12 @@ //! Machinery for [task-queue](https://html.spec.whatwg.org/multipage/#task-queue). use std::cell::Cell; -use std::collections::{HashMap, HashSet, VecDeque}; +use std::collections::VecDeque; use std::default::Default; use base::id::PipelineId; use crossbeam_channel::{self, Receiver, Sender}; +use rustc_hash::{FxHashMap, FxHashSet}; use strum::VariantArray; use crate::dom::bindings::cell::DomRefCell; @@ -47,9 +48,9 @@ pub(crate) struct TaskQueue { /// A "business" counter, reset for each iteration of the event-loop taken_task_counter: Cell, /// Tasks that will be throttled for as long as we are "busy". - throttled: DomRefCell>>, + throttled: DomRefCell>>, /// Tasks for not fully-active documents. - inactive: DomRefCell>>, + inactive: DomRefCell>>, } impl TaskQueue { @@ -68,7 +69,7 @@ impl TaskQueue { /// fn release_tasks_for_fully_active_documents( &self, - fully_active: &HashSet, + fully_active: &FxHashSet, ) -> Vec { self.inactive .borrow_mut() @@ -103,7 +104,7 @@ impl TaskQueue { /// Process incoming tasks, immediately sending priority ones downstream, /// and categorizing potential throttles. - fn process_incoming_tasks(&self, first_msg: T, fully_active: &HashSet) { + fn process_incoming_tasks(&self, first_msg: T, fully_active: &FxHashSet) { // 1. Make any previously stored task from now fully-active document available. let mut incoming = self.release_tasks_for_fully_active_documents(fully_active); @@ -196,14 +197,17 @@ impl TaskQueue { } /// Take all tasks again and then run `recv()`. - pub(crate) fn take_tasks_and_recv(&self, fully_active: &HashSet) -> Result { + pub(crate) fn take_tasks_and_recv( + &self, + fully_active: &FxHashSet, + ) -> Result { self.take_tasks(T::wake_up_msg(), fully_active); self.recv() } /// Drain the queue for the current iteration of the event-loop. /// Holding-back throttles above a given high-water mark. - pub(crate) fn take_tasks(&self, first_msg: T, fully_active: &HashSet) { + pub(crate) fn take_tasks(&self, first_msg: T, fully_active: &FxHashSet) { // High-watermark: once reached, throttled tasks will be held-back. const PER_ITERATION_MAX: u64 = 5; // Always first check for new tasks, but don't reset 'taken_task_counter'. diff --git a/components/script/timers.rs b/components/script/timers.rs index 1ea19108d50..681ef183336 100644 --- a/components/script/timers.rs +++ b/components/script/timers.rs @@ -4,7 +4,7 @@ use std::cell::Cell; use std::cmp::{Ord, Ordering}; -use std::collections::{HashMap, VecDeque}; +use std::collections::VecDeque; use std::default::Default; use std::rc::Rc; use std::time::{Duration, Instant}; @@ -14,6 +14,7 @@ use deny_public_fields::DenyPublicFields; use js::jsapi::Heap; use js::jsval::{JSVal, UndefinedValue}; use js::rust::HandleValue; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use servo_config::pref; use timers::{BoxedTimerCallback, TimerEventRequest}; @@ -361,7 +362,7 @@ pub(crate) struct JsTimerHandle(i32); pub(crate) struct JsTimers { next_timer_handle: Cell, /// - active_timers: DomRefCell>, + active_timers: DomRefCell>, /// The nesting level of the currently executing timer task or 0. nesting_level: Cell, /// Used to introduce a minimum delay in event intervals @@ -415,7 +416,7 @@ impl Default for JsTimers { fn default() -> Self { JsTimers { next_timer_handle: Cell::new(JsTimerHandle(1)), - active_timers: DomRefCell::new(HashMap::new()), + active_timers: DomRefCell::new(FxHashMap::default()), nesting_level: Cell::new(0), min_duration: Cell::new(None), } diff --git a/components/shared/constellation/Cargo.toml b/components/shared/constellation/Cargo.toml index 63874814f24..003843ae7f0 100644 --- a/components/shared/constellation/Cargo.toml +++ b/components/shared/constellation/Cargo.toml @@ -24,6 +24,7 @@ embedder_traits = { workspace = true } euclid = { workspace = true } fonts_traits = { workspace = true } fnv = { workspace = true } +rustc-hash = { workspace = true } http = { workspace = true } hyper_serde = { workspace = true } ipc-channel = { workspace = true } diff --git a/components/shared/constellation/structured_data/mod.rs b/components/shared/constellation/structured_data/mod.rs index 2531e405a22..270fda331df 100644 --- a/components/shared/constellation/structured_data/mod.rs +++ b/components/shared/constellation/structured_data/mod.rs @@ -8,14 +8,13 @@ mod serializable; mod transferable; -use std::collections::HashMap; - use base::id::{ BlobId, DomExceptionId, DomMatrixId, DomPointId, DomQuadId, DomRectId, ImageBitmapId, MessagePortId, OffscreenCanvasId, QuotaExceededErrorId, }; use log::warn; use malloc_size_of_derive::MallocSizeOf; +use rustc_hash::{FxBuildHasher, FxHashMap}; use serde::{Deserialize, Serialize}; pub use serializable::*; use strum::IntoEnumIterator; @@ -28,35 +27,35 @@ pub struct StructuredSerializedData { /// Data serialized by SpiderMonkey. pub serialized: Vec, /// Serialized in a structured callback, - pub blobs: Option>, + pub blobs: Option>, /// Serialized point objects. - pub points: Option>, + pub points: Option>, /// Serialized rect objects. - pub rects: Option>, + pub rects: Option>, /// Serialized quad objects. - pub quads: Option>, + pub quads: Option>, /// Serialized matrix objects. - pub matrices: Option>, + pub matrices: Option>, /// Serialized exception objects. - pub exceptions: Option>, + pub exceptions: Option>, /// Serialized quota exceeded errors. pub quota_exceeded_errors: - Option>, + Option>, /// Transferred objects. - pub ports: Option>, + pub ports: Option>, /// Transform streams transferred objects. - pub transform_streams: Option>, + pub transform_streams: Option>, /// Serialized image bitmap objects. - pub image_bitmaps: Option>, + pub image_bitmaps: Option>, /// Transferred image bitmap objects. - pub transferred_image_bitmaps: Option>, + pub transferred_image_bitmaps: Option>, /// Transferred offscreen canvas objects. - pub offscreen_canvases: Option>, + pub offscreen_canvases: Option>, } impl StructuredSerializedData { fn is_empty(&self, val: Transferrable) -> bool { - fn is_field_empty(field: &Option>) -> bool { + fn is_field_empty(field: &Option>) -> bool { field.as_ref().is_none_or(|h| h.is_empty()) } match val { @@ -74,7 +73,7 @@ impl StructuredSerializedData { fn clone_all_of_type(&self, cloned: &mut StructuredSerializedData) { let existing = T::source(self); let Some(existing) = existing else { return }; - let mut clones = HashMap::with_capacity(existing.len()); + let mut clones = FxHashMap::with_capacity_and_hasher(existing.len(), FxBuildHasher); for (original_id, obj) in existing.iter() { if let Some(clone) = obj.clone_for_broadcast() { diff --git a/components/shared/constellation/structured_data/serializable.rs b/components/shared/constellation/structured_data/serializable.rs index 62cc158421b..a73391d1dec 100644 --- a/components/shared/constellation/structured_data/serializable.rs +++ b/components/shared/constellation/structured_data/serializable.rs @@ -8,7 +8,6 @@ //! be passed through the Constellation. use std::cell::RefCell; -use std::collections::HashMap; use std::path::PathBuf; use base::id::{ @@ -19,6 +18,7 @@ use euclid::default::Transform3D; use malloc_size_of_derive::MallocSizeOf; use net_traits::filemanager_thread::RelativePos; use pixels::Snapshot; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use servo_url::ImmutableOrigin; use strum::EnumIter; @@ -36,9 +36,9 @@ where /// Only return None if cloning is impossible. fn clone_for_broadcast(&self) -> Option; /// The field from which to clone values. - fn source(data: &StructuredSerializedData) -> &Option>; + fn source(data: &StructuredSerializedData) -> &Option>; /// The field into which to place cloned values. - fn destination(data: &mut StructuredSerializedData) -> &mut Option>; + fn destination(data: &mut StructuredSerializedData) -> &mut Option>; } /// All the DOM interfaces that can be serialized. @@ -168,15 +168,11 @@ impl FileBlob { impl BroadcastClone for BlobImpl { type Id = BlobId; - fn source( - data: &StructuredSerializedData, - ) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.blobs } - fn destination( - data: &mut StructuredSerializedData, - ) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.blobs } @@ -304,15 +300,11 @@ pub struct DomPoint { impl BroadcastClone for DomPoint { type Id = DomPointId; - fn source( - data: &StructuredSerializedData, - ) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.points } - fn destination( - data: &mut StructuredSerializedData, - ) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.points } @@ -337,15 +329,11 @@ pub struct DomRect { impl BroadcastClone for DomRect { type Id = DomRectId; - fn source( - data: &StructuredSerializedData, - ) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.rects } - fn destination( - data: &mut StructuredSerializedData, - ) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.rects } @@ -370,15 +358,11 @@ pub struct DomQuad { impl BroadcastClone for DomQuad { type Id = DomQuadId; - fn source( - data: &StructuredSerializedData, - ) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.quads } - fn destination( - data: &mut StructuredSerializedData, - ) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.quads } @@ -399,15 +383,11 @@ pub struct DomMatrix { impl BroadcastClone for DomMatrix { type Id = DomMatrixId; - fn source( - data: &StructuredSerializedData, - ) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.matrices } - fn destination( - data: &mut StructuredSerializedData, - ) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.matrices } @@ -426,15 +406,11 @@ pub struct DomException { impl BroadcastClone for DomException { type Id = DomExceptionId; - fn source( - data: &StructuredSerializedData, - ) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.exceptions } - fn destination( - data: &mut StructuredSerializedData, - ) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.exceptions } @@ -454,11 +430,11 @@ pub struct SerializableQuotaExceededError { impl BroadcastClone for SerializableQuotaExceededError { type Id = QuotaExceededErrorId; - fn source(data: &StructuredSerializedData) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.quota_exceeded_errors } - fn destination(data: &mut StructuredSerializedData) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.quota_exceeded_errors } @@ -476,15 +452,11 @@ pub struct SerializableImageBitmap { impl BroadcastClone for SerializableImageBitmap { type Id = ImageBitmapId; - fn source( - data: &StructuredSerializedData, - ) -> &Option> { + fn source(data: &StructuredSerializedData) -> &Option> { &data.image_bitmaps } - fn destination( - data: &mut StructuredSerializedData, - ) -> &mut Option> { + fn destination(data: &mut StructuredSerializedData) -> &mut Option> { &mut data.image_bitmaps }