aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/intern.rs
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-04-02 17:11:08 +0100
committerJonas Schievink <[email protected]>2021-04-02 17:11:08 +0100
commit76452956e4ee3be89a9da69cccadfb980b075049 (patch)
tree77334a48103518d4cd9252d9304a1abcb3f76cf8 /crates/hir_def/src/intern.rs
parentafd83e0686512ad2678a2b0bad3b1421692a28bf (diff)
Split `Intern::drop` into hot and cold path
Diffstat (limited to 'crates/hir_def/src/intern.rs')
-rw-r--r--crates/hir_def/src/intern.rs39
1 files changed, 23 insertions, 16 deletions
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs
index 18c8ab246..785d9e3c6 100644
--- a/crates/hir_def/src/intern.rs
+++ b/crates/hir_def/src/intern.rs
@@ -53,31 +53,38 @@ impl<T: Internable> Interned<T> {
53} 53}
54 54
55impl<T: Internable + ?Sized> Drop for Interned<T> { 55impl<T: Internable + ?Sized> Drop for Interned<T> {
56 #[inline]
56 fn drop(&mut self) { 57 fn drop(&mut self) {
57 // When the last `Ref` is dropped, remove the object from the global map. 58 // When the last `Ref` is dropped, remove the object from the global map.
58 if Arc::strong_count(&self.arc) == 2 { 59 if Arc::strong_count(&self.arc) == 2 {
59 // Only `self` and the global map point to the object. 60 // Only `self` and the global map point to the object.
60 61
61 let storage = T::storage().get(); 62 self.drop_slow();
62 let shard_idx = storage.determine_map(&self.arc); 63 }
63 let shard = &storage.shards()[shard_idx]; 64 }
64 let mut shard = shard.write(); 65}
66
67impl<T: Internable + ?Sized> Interned<T> {
68 #[cold]
69 fn drop_slow(&mut self) {
70 let storage = T::storage().get();
71 let shard_idx = storage.determine_map(&self.arc);
72 let shard = &storage.shards()[shard_idx];
73 let mut shard = shard.write();
65 74
66 // FIXME: avoid double lookup 75 // FIXME: avoid double lookup
67 let (arc, _) = 76 let (arc, _) = shard.get_key_value(&self.arc).expect("interned value removed prematurely");
68 shard.get_key_value(&self.arc).expect("interned value removed prematurely");
69 77
70 if Arc::strong_count(arc) != 2 { 78 if Arc::strong_count(arc) != 2 {
71 // Another thread has interned another copy 79 // Another thread has interned another copy
72 return; 80 return;
73 } 81 }
74 82
75 shard.remove(&self.arc); 83 shard.remove(&self.arc);
76 84
77 // Shrink the backing storage if the shard is less than 50% occupied. 85 // Shrink the backing storage if the shard is less than 50% occupied.
78 if shard.len() * 2 < shard.capacity() { 86 if shard.len() * 2 < shard.capacity() {
79 shard.shrink_to_fit(); 87 shard.shrink_to_fit();
80 }
81 } 88 }
82 } 89 }
83} 90}