servo / string-cache

String interning for Rust
Apache License 2.0
194 stars 77 forks source link

fix: move debug_assert check #275

Closed YoniFeng closed 1 year ago

YoniFeng commented 1 year ago

Fix needed after #268 The fix is only for debug_assert correctness. There's no functional effect. i.e. version 0.8.6 might cause debug tests to fail, but it isn't a (functionally) breaking change.

Explanation Moving the lock to be per-bucket changed the DYNAMIC_SET's API so that it doesn't need to be locked (i.e. DYANMIC_SET is not wrapped with a Mutex). The Atom's fn drop changed from

fn drop(&mut self) {
        if self.tag() == DYNAMIC_TAG {
            let entry = self.unsafe_data.get() as *const Entry;
            if unsafe { &*entry }.ref_count.fetch_sub(1, SeqCst) == 1 {
                drop_slow(self)
            }
        }

        // Out of line to guide inlining.
        fn drop_slow<Static>(this: &mut Atom<Static>) {
            DYNAMIC_SET
                .lock()
                .remove(this.unsafe_data.get() as *mut Entry);
        }
    }

to

impl<Static> Drop for Atom<Static> {
    #[inline]
    fn drop(&mut self) {
        if self.tag() == DYNAMIC_TAG {
            let entry = self.unsafe_data.get() as *const Entry;
            if unsafe { &*entry }.ref_count.fetch_sub(1, SeqCst) == 1 {
                drop_slow(self)
            }
        }

        // Out of line to guide inlining.
        fn drop_slow<Static>(this: &mut Atom<Static>) {
            DYNAMIC_SET.remove(this.unsafe_data.get() as *mut Entry);
        }
    }

(the lock() is gone) Now when we enter DYNAMIC_SET.remove(), there's no longer a lock guarantee. Until we lock the bucket, another thread could be in the middle of performing a DYNAMIC_SET.insert() for the same string. Therefore, the debug_assert!(value.ref_count.load(SeqCst) == 0) is premature - it needs to occur after we take the lock for the bucket.

Caught at https://github.com/swc-project/swc/pull/6980 in a failed test.

jdm commented 1 year ago

@bors-servo r+

bors-servo commented 1 year ago

:pushpin: Commit 120ba6c has been approved by jdm

bors-servo commented 1 year ago

:hourglass: Testing commit 120ba6c88e9337a810149b5afa4eecf32d8006d8 with merge 7f3789bddce385472aea95ae4c47df738d206f48...

bors-servo commented 1 year ago

:sunny: Test successful - checks-github Approved by: jdm Pushing 7f3789bddce385472aea95ae4c47df738d206f48 to master...

YoniFeng commented 1 year ago

@jdm hate to have to ask again.. but could you please bump another version?

hopefully this is the last activity on this crate for a long time :)

jdm commented 1 year ago

Done!