diff --git a/Cargo.toml b/Cargo.toml index dbdad57..d98a065 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "string_cache" -version = "0.7.3" # Also update README.md when making a semver-breaking change +version = "0.7.4" # Also update README.md when making a semver-breaking change authors = [ "The Servo Project Developers" ] description = "A string interning library for Rust, developed as part of the Servo project." license = "MIT / Apache-2.0" @@ -41,3 +41,7 @@ string_cache_codegen = { version = "0.4", path = "./string-cache-codegen" } [build-dependencies] string_cache_codegen = { version = "0.4", path = "./string-cache-codegen" } + +[[test]] +name = "small-stack" +harness = false diff --git a/src/atom.rs b/src/atom.rs index f575c02..ac1f397 100644 --- a/src/atom.rs +++ b/src/atom.rs @@ -39,7 +39,7 @@ const NB_BUCKETS: usize = 1 << 12; // 4096 const BUCKET_MASK: u64 = (1 << 12) - 1; struct StringCache { - buckets: [Option>; NB_BUCKETS], + buckets: Box<[Option>; NB_BUCKETS]>, } lazy_static! { @@ -67,8 +67,13 @@ impl StringCacheEntry { impl StringCache { fn new() -> StringCache { + type T = Option>; + let _static_assert_size_eq = std::mem::transmute::; + let vec = std::mem::ManuallyDrop::new(vec![0_usize; NB_BUCKETS]); StringCache { - buckets: unsafe { mem::zeroed() }, + buckets: unsafe { + Box::from_raw(vec.as_ptr() as *mut [T; NB_BUCKETS]) + }, } } diff --git a/tests/small-stack.rs b/tests/small-stack.rs new file mode 100644 index 0000000..300b142 --- /dev/null +++ b/tests/small-stack.rs @@ -0,0 +1,12 @@ +// Regression test for https://github.com/servo/html5ever/issues/393 +// +// Create a dynamic atom − causing initialization of the golbal hash map − +// in a thread that has a small stack. +// +// This is a separate test program rather than a `#[test] fn` among others +// to make sure that nothing else has already initialized the map in this process. +fn main() { + std::thread::Builder::new().stack_size(50_000).spawn(|| { + string_cache::DefaultAtom::from("12345678"); + }).unwrap().join().unwrap() +}