diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/intern.rs | 39 |
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 | ||
55 | impl<T: Internable + ?Sized> Drop for Interned<T> { | 55 | impl<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 | |||
67 | impl<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 | } |