Split Intern::drop into hot and cold path

This commit is contained in:
Jonas Schievink 2021-04-02 18:11:08 +02:00
parent afd83e0686
commit 76452956e4

View file

@ -53,19 +53,27 @@ impl<T: Internable> Interned<T> {
} }
impl<T: Internable + ?Sized> Drop for Interned<T> { impl<T: Internable + ?Sized> Drop for Interned<T> {
#[inline]
fn drop(&mut self) { fn drop(&mut self) {
// When the last `Ref` is dropped, remove the object from the global map. // When the last `Ref` is dropped, remove the object from the global map.
if Arc::strong_count(&self.arc) == 2 { if Arc::strong_count(&self.arc) == 2 {
// Only `self` and the global map point to the object. // Only `self` and the global map point to the object.
self.drop_slow();
}
}
}
impl<T: Internable + ?Sized> Interned<T> {
#[cold]
fn drop_slow(&mut self) {
let storage = T::storage().get(); let storage = T::storage().get();
let shard_idx = storage.determine_map(&self.arc); let shard_idx = storage.determine_map(&self.arc);
let shard = &storage.shards()[shard_idx]; let shard = &storage.shards()[shard_idx];
let mut shard = shard.write(); let mut shard = shard.write();
// FIXME: avoid double lookup // FIXME: avoid double lookup
let (arc, _) = let (arc, _) = shard.get_key_value(&self.arc).expect("interned value removed prematurely");
shard.get_key_value(&self.arc).expect("interned value removed prematurely");
if Arc::strong_count(arc) != 2 { if Arc::strong_count(arc) != 2 {
// Another thread has interned another copy // Another thread has interned another copy
@ -80,7 +88,6 @@ impl<T: Internable + ?Sized> Drop for Interned<T> {
} }
} }
} }
}
/// Compares interned `Ref`s using pointer equality. /// Compares interned `Ref`s using pointer equality.
impl<T: Internable + ?Sized> PartialEq for Interned<T> { impl<T: Internable + ?Sized> PartialEq for Interned<T> {