@@ -190,6 +190,28 @@ where
190190 // ensures that they are not reused while being accessed.
191191 unsafe { & * self . fields . get ( ) }
192192 }
193+
194+ /// Returns memory usage information about the interned value.
195+ ///
196+ /// # Safety
197+ ///
198+ /// The `MemoTable` must belong to a `Value` of the correct type. Additionally, the
199+ /// lock must be held for the shard containing the value.
200+ #[ cfg( all( not( feature = "shuttle" ) , feature = "salsa_unstable" ) ) ]
201+ unsafe fn memory_usage ( & self , memo_table_types : & MemoTableTypes ) -> crate :: SlotInfo {
202+ // SAFETY: The caller guarantees we hold the lock for the shard containing the value, so we
203+ // have at-least read-only access to the value's memos.
204+ let memos = unsafe { & * self . memos . get ( ) } ;
205+ // SAFETY: The caller guarantees this is the correct types table.
206+ let memos = unsafe { memo_table_types. attach_memos ( memos) } ;
207+
208+ crate :: SlotInfo {
209+ debug_name : C :: DEBUG_NAME ,
210+ size_of_metadata : std:: mem:: size_of :: < Self > ( ) - std:: mem:: size_of :: < C :: Fields < ' _ > > ( ) ,
211+ size_of_fields : std:: mem:: size_of :: < C :: Fields < ' _ > > ( ) ,
212+ memos : memos. memory_usage ( ) ,
213+ }
214+ }
193215}
194216
195217impl < C : Configuration > Default for JarImpl < C > {
@@ -680,7 +702,7 @@ where
680702 //
681703 // # Safety
682704 //
683- // The lock must be held.
705+ // The lock must be held for the shard containing the value .
684706 unsafe fn value_hash < ' db > ( & ' db self , id : Id , zalsa : & ' db Zalsa ) -> u64 {
685707 // This closure is only called if the table is resized. So while it's expensive
686708 // to lookup all values, it will only happen rarely.
@@ -694,7 +716,7 @@ where
694716 //
695717 // # Safety
696718 //
697- // The lock must be held.
719+ // The lock must be held for the shard containing the value .
698720 unsafe fn value_eq < ' db , Key > (
699721 id : Id ,
700722 key : & Key ,
@@ -830,6 +852,31 @@ where
830852 fn memo_table_types ( & self ) -> Arc < MemoTableTypes > {
831853 self . memo_table_types . clone ( )
832854 }
855+
856+ /// Returns memory usage information about any interned values.
857+ #[ cfg( all( not( feature = "shuttle" ) , feature = "salsa_unstable" ) ) ]
858+ fn memory_usage ( & self , db : & dyn Database ) -> Option < Vec < crate :: SlotInfo > > {
859+ use parking_lot:: lock_api:: RawMutex ;
860+
861+ for shard in self . shards . iter ( ) {
862+ // SAFETY: We do not hold any active mutex guards.
863+ unsafe { shard. raw ( ) . lock ( ) } ;
864+ }
865+
866+ let memory_usage = self
867+ . entries ( db)
868+ // SAFETY: The memo table belongs to a value that we allocated, so it
869+ // has the correct type. Additionally, we are holding the locks for all shards.
870+ . map ( |value| unsafe { value. memory_usage ( & self . memo_table_types ) } )
871+ . collect ( ) ;
872+
873+ for shard in self . shards . iter ( ) {
874+ // SAFETY: We acquired the locks for all shards.
875+ unsafe { shard. raw ( ) . unlock ( ) } ;
876+ }
877+
878+ Some ( memory_usage)
879+ }
833880}
834881
835882impl < C > std:: fmt:: Debug for IngredientImpl < C >
0 commit comments