Bug 1475197 - Part 2: Revendor Rust dependencies. r=emilio draft
authorCameron McCormack <cam@mcc.id.au>
Wed, 01 Aug 2018 10:29:48 +1000
changeset 825253 ac66a76ff0f38d3b5aa07fc5ac273f06a85ea589
parent 825252 065b94b9803c665aea86ac7b1432b1e29970ae7e
push id118046
push userbmo:cam@mcc.id.au
push dateWed, 01 Aug 2018 05:40:57 +0000
reviewersemilio
bugs1475197
milestone63.0a1
Bug 1475197 - Part 2: Revendor Rust dependencies. r=emilio MozReview-Commit-ID: HRMXpPx8Lls
Cargo.lock
third_party/rust/thin-slice/.cargo-checksum.json
third_party/rust/thin-slice/Cargo.toml
third_party/rust/thin-slice/README.md
third_party/rust/thin-slice/src/lib.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1138,16 +1138,17 @@ dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "malloc_size_of_derive"
 version = "0.0.1"
 dependencies = [
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1808,16 +1809,17 @@ dependencies = [
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "semver"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1975,16 +1977,17 @@ dependencies = [
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "style_derive 0.0.1",
  "style_traits 0.0.1",
+ "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2105,16 +2108,21 @@ name = "textwrap"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "thin-slice"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "thread_local"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2724,16 +2732,17 @@ dependencies = [
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
 "checksum syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c67da57e61ebc7b7b6fff56bb34440ca3a83db037320b0507af4c10368deda7d"
 "checksum synstructure 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "98cad891cd238c98e1f0aec9f7c0f620aa696e4e5f7daba56ac67b5e86a6b049"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
+"checksum thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
 "checksum thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf947d192a9be60ef5131cc7a4648886ba89d712f16700ebbf80c8a69d05d48f"
 "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
 "checksum tokio-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "febd81b3e2ef615c6c8077347b33f3f3deec3d708ecd08194c9707b7a1eccfc9"
 "checksum tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ab83e7adb5677e42e405fa4ceff75659d93c4d7d7dd22f52fcec59ee9f02af"
 "checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9"
 "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
 "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/thin-slice/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"bc648e7794ea9bf0b7b520a0ba079ef65226158dc6ece1e617beadc52456e1b7","README.md":"4a83c0adbfdd3ae8047fe4fd26536d27b4e8db813f9926ee8ab09b784294e50f","src/lib.rs":"5b1f2bfc9edfc6036a8880cde88f862931eec5036e6cf63690f82921053b29fe"},"package":"8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/thin-slice/Cargo.toml
@@ -0,0 +1,23 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "thin-slice"
+version = "0.1.1"
+authors = ["Cameron McCormack <cam@mcc.id.au>"]
+description = "An owned slice that packs the slice storage into a single word when possible"
+readme = "README.md"
+keywords = ["slice", "tagged", "pointer"]
+license = "MPL-2.0"
+repository = "https://github.com/heycam/thin-slice"
+
+[dependencies]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/thin-slice/README.md
@@ -0,0 +1,49 @@
+# thin-slice
+
+An owned slice that packs the slice storage into a single word when possible.
+
+## Usage
+
+```rust
+extern crate thin_slice;
+
+use std::mem;
+use thin_slice::ThinBoxedSlice;
+
+struct Ticket {
+    numbers: Box<[u8]>,
+    winning: bool,
+}
+
+struct ThinTicket {
+    numbers: ThinBoxedSlice<u8>,
+    winning: bool,
+}
+
+fn main() {
+    let nums = vec![4, 8, 15, 16, 23, 42].into_boxed_slice();
+    let ticket = ThinTicket {
+        numbers: nums.into(),
+        winning: false,
+    };
+    println!("Numbers: {:?}", ticket.numbers);
+
+    println!("size_of::<usize>():      {}", mem::size_of::<usize>());
+    println!("size_of::<Ticket>():     {}", mem::size_of::<Ticket>());
+    println!("size_of::<ThinTicket>(): {}", mem::size_of::<ThinTicket>());
+}
+```
+
+Output on `x86_64`:
+
+```
+Numbers: [4, 8, 15, 16, 23, 42]
+size_of::<usize>():      8
+size_of::<Ticket>():     24
+size_of::<ThinTicket>(): 16
+```
+
+## License
+
+thin-slice is distributed under the terms of the
+[Mozilla Public License, v. 2.0](https://www.mozilla.org/MPL/2.0/).
new file mode 100644
--- /dev/null
+++ b/third_party/rust/thin-slice/src/lib.rs
@@ -0,0 +1,544 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! An owned slice that tries to use only one word of storage.
+//!
+//! `ThinBoxedSlice<T>` can be used in place of `Box<[T]>` on the `x86_64`
+//! architecture to hold ownership of a slice when it's important to reduce
+//! memory usage of the box itself. When the slice length is less than
+//! `0xffff`, a single word is used to encode the slice pointer and length.
+//! When it is greater than `0xffff`, a heap allocation is used to store the
+//! fat pointer representing the slice.
+//!
+//! A `ThinBoxedSlice<T>` is always created by converting from a `Box<[T]>`.
+//!
+//! On any architecture other than `x86_64`, a `ThinBoxedSlice<T>` will simply
+//! use a `Box<[T]>` internally.
+//!
+//! # Examples
+//!
+//! Creating a `ThinBoxedSlice`:
+//!
+//! ```
+//! # use thin_slice::ThinBoxedSlice;
+//! let fat_pointer = vec![10, 20, 30].into_boxed_slice();
+//! let thin_pointer: ThinBoxedSlice<_> = fat_pointer.into();
+//! ```
+
+use std::cmp::Ordering;
+use std::fmt;
+use std::hash::{Hash, Hasher};
+#[cfg(target_arch = "x86_64")]
+use std::marker::PhantomData;
+#[cfg(target_arch = "x86_64")]
+use std::mem;
+use std::ops::{Deref, DerefMut};
+#[cfg(target_arch = "x86_64")]
+use std::ptr::NonNull;
+#[cfg(target_arch = "x86_64")]
+use std::slice;
+
+/// An owned slice that tries to use only one word of storage.
+///
+/// See the [module-level documentation](index.html) for more.
+pub struct ThinBoxedSlice<T> {
+    /// Storage for the slice.
+    ///
+    /// Once `std::num::NonZeroUsize` has stabilized, we can switch to that.
+    ///
+    /// The value stored here depends on the length of the slice.
+    ///
+    /// If len = 0, `data` will be `1usize`.
+    ///
+    /// If 0 < len < 0xffff, then len will be stored in the top 16 bits of
+    /// data, and the lower 48 bits will be the pointer to the elements.
+    ///
+    /// If len >= 0xffff, then the top 16 bits of data will be 0xffff, and
+    /// the lower 48 bits will be a pointer to a heap allocated `Box<[T]>`.
+    #[cfg(target_arch = "x86_64")]
+    data: NonNull<()>,
+
+    #[cfg(not(target_arch = "x86_64"))]
+    data: Box<[T]>,
+
+    #[cfg(target_arch = "x86_64")]
+    _phantom: PhantomData<Box<[T]>>,
+}
+
+#[cfg(target_arch = "x86_64")]
+const TAG_MASK: usize = 0xffff000000000000;
+
+#[cfg(target_arch = "x86_64")]
+const PTR_MASK: usize = 0x0000ffffffffffff;
+
+#[cfg(target_arch = "x86_64")]
+const PTR_HIGH: usize = 0x0000800000000000;
+
+#[cfg(target_arch = "x86_64")]
+const TAG_SHIFT: usize = 48;
+
+#[cfg(target_arch = "x86_64")]
+const TAG_LIMIT: usize = TAG_MASK >> TAG_SHIFT;
+
+#[cfg(target_arch = "x86_64")]
+enum Storage<T> {
+    Inline(*mut T, usize),
+    Spilled(*mut Box<[T]>),
+}
+
+#[cfg(target_arch = "x86_64")]
+impl<T> ThinBoxedSlice<T> {
+    /// Constructs a `ThinBoxedSlice` from a raw pointer.
+    ///
+    /// Like `Box::from_raw`, after calling this function, the raw pointer is
+    /// owned by the resulting `ThinBoxedSlice`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use thin_slice::ThinBoxedSlice;
+    /// let x = vec![10, 20, 30].into_boxed_slice();       // a Box<[i32]>
+    /// let ptr = Box::into_raw(x);                        // a *mut [i32]
+    /// let x = unsafe { ThinBoxedSlice::from_raw(ptr) };  // a ThinBoxedSlice<i32>
+    /// ```
+    #[inline]
+    pub unsafe fn from_raw(raw: *mut [T]) -> ThinBoxedSlice<T> {
+        let len = (*raw).len();
+        let ptr = (*raw).as_mut_ptr();
+        let storage = if len == 0 {
+            Storage::Inline(1usize as *mut _, 0)
+        } else if len < TAG_LIMIT {
+            Storage::Inline(ptr, len)
+        } else {
+            let boxed_slice = Box::from_raw(raw);
+            Storage::Spilled(Box::into_raw(Box::new(boxed_slice)))
+        };
+        ThinBoxedSlice {
+            data: storage.into_data(),
+            _phantom: PhantomData,
+        }
+    }
+
+    /// Consumes the `ThinBoxedSlice`, returning a raw pointer to the slice
+    /// it owned.
+    ///
+    /// Like `Box::into_raw`, after calling this function, the caller is
+    /// responsible for the memory previously managed by the `ThinBoxedSlice`.
+    /// In particular, the caller should properly destroy the `[T]` and release
+    /// the memory. The proper way to do so is to convert the raw pointer back
+    /// into a `Box` or a `ThinBoxedSlice`, with either the `Box::from_raw` or
+    /// `ThinBoxedSlice::from_raw` functions.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use thin_slice::ThinBoxedSlice;
+    /// let x = vec![10, 20, 30].into_boxed_slice();
+    /// let x = ThinBoxedSlice::from(x);
+    /// let ptr = ThinBoxedSlice::into_raw(x);
+    /// ```
+    #[inline]
+    pub fn into_raw(b: ThinBoxedSlice<T>) -> *mut [T] {
+        unsafe {
+            match b.into_storage() {
+                Storage::Inline(ptr, len) => {
+                    slice::from_raw_parts_mut(ptr, len)
+                }
+                Storage::Spilled(ptr) => {
+                    Box::into_raw(*Box::from_raw(ptr))
+                }
+            }
+        }
+    }
+
+    /// Consumes and leaks the `ThinBoxedSlice`, returning a mutable reference,
+    /// `&'a mut [T]`. Here, the lifetime `'a` may be chosen to be `'static`.
+    ///
+    /// Like `Box::leak`, this function is mainly useful for data that lives
+    /// for the remainder of the program's life. Dropping the returned
+    /// reference will cause a memory leak. If this is not acceptable, the
+    /// reference should first be wrapped with the `Box::from_raw` function
+    /// producing a `Box`, or with the `ThinBoxedSlice::from_raw` function
+    /// producing a `ThinBoxedSlice`. This value can then be dropped which will
+    /// properly destroy `[T]` and release the allocated memory.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use thin_slice::ThinBoxedSlice;
+    /// fn main() {
+    ///     let x = ThinBoxedSlice::from(vec![1, 2, 3].into_boxed_slice());
+    ///     let static_ref = ThinBoxedSlice::leak(x);
+    ///     static_ref[0] = 4;
+    ///     assert_eq!(*static_ref, [4, 2, 3]);
+    /// }
+    /// ```
+    #[inline]
+    pub fn leak(b: ThinBoxedSlice<T>) -> &'static mut [T] {
+        unsafe { &mut *ThinBoxedSlice::into_raw(b) }
+    }
+
+    /// Returns a pointer to the heap allocation that stores the fat pointer
+    /// to the slice, if any. This is useful for systems that need to measure
+    /// memory allocation, but is otherwise an opaque pointer.
+    #[inline]
+    pub fn spilled_storage(&self) -> Option<*const ()> {
+        match self.storage() {
+            Storage::Inline(..) => None,
+            Storage::Spilled(ptr) => Some(ptr as *const ()),
+        }
+    }
+
+    #[inline]
+    fn storage(&self) -> Storage<T> {
+        Storage::from_data(self.data.clone())
+    }
+
+    #[inline]
+    fn into_storage(self) -> Storage<T> {
+        let storage = self.storage();
+        mem::forget(self);
+        storage
+    }
+}
+
+#[cfg(not(target_arch = "x86_64"))]
+impl<T> ThinBoxedSlice<T> {
+    /// Constructs a `ThinBoxedSlice` from a raw pointer.
+    ///
+    /// Like `Box::from_raw`, after calling this function, the raw pointer is
+    /// owned by the resulting `ThinBoxedSlice`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use thin_slice::ThinBoxedSlice;
+    /// let x = vec![10, 20, 30].into_boxed_slice();       // a Box<[i32]>
+    /// let ptr = Box::into_raw(x);                        // a *mut [i32]
+    /// let x = unsafe { ThinBoxedSlice::from_raw(ptr) };  // a ThinBoxedSlice<i32>
+    /// ```
+    #[inline]
+    pub unsafe fn from_raw(raw: *mut [T]) -> ThinBoxedSlice<T> {
+        ThinBoxedSlice {
+            data: Box::from_raw(raw),
+        }
+    }
+
+    /// Consumes the `ThinBoxedSlice`, returning a raw pointer to the slice
+    /// it owned.
+    ///
+    /// Like `Box::into_raw`, after calling this function, the caller is
+    /// responsible for the memory previously managed by the `ThinBoxedSlice`.
+    /// In particular, the caller should properly destroy the `[T]` and release
+    /// the memory. The proper way to do so is to convert the raw pointer back
+    /// into a `Box` or a `ThinBoxedSlice`, with either the `Box::from_raw` or
+    /// `ThinBoxedSlice::from_raw` functions.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use thin_slice::ThinBoxedSlice;
+    /// let x = vec![10, 20, 30].into_boxed_slice();
+    /// let x = ThinBoxedSlice::from(x);
+    /// let ptr = ThinBoxedSlice::into_raw(x);
+    /// ```
+    #[inline]
+    pub fn into_raw(b: ThinBoxedSlice<T>) -> *mut [T] {
+        Box::into_raw(b.data)
+    }
+
+    /// Consumes and leaks the `ThinBoxedSlice`, returning a mutable reference,
+    /// `&'a mut [T]`. Here, the lifetime `'a` may be chosen to be `'static`.
+    ///
+    /// Like `Box::leak`, this function is mainly useful for data that lives
+    /// for the remainder of the program's life. Dropping the returned
+    /// reference will cause a memory leak. If this is not acceptable, the
+    /// reference should first be wrapped with the `Box::from_raw` function
+    /// producing a `Box`, or with the `ThinBoxedSlice::from_raw` function
+    /// producing a `ThinBoxedSlice`. This value can then be dropped which will
+    /// properly destroy `[T]` and release the allocated memory.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use thin_slice::ThinBoxedSlice;
+    /// fn main() {
+    ///     let x = ThinBoxedSlice::from(vec![1, 2, 3].into_boxed_slice());
+    ///     let static_ref = ThinBoxedSlice::leak(x);
+    ///     static_ref[0] = 4;
+    ///     assert_eq!(*static_ref, [4, 2, 3]);
+    /// }
+    /// ```
+    #[inline]
+    pub fn leak<'a>(b: ThinBoxedSlice<T>) -> &'a mut [T] where T: 'a {
+        Box::leak(b.data)
+    }
+
+    /// Returns a pointer to the heap allocation that stores the fat pointer
+    /// to the slice, if any. This is useful for systems that need to measure
+    /// memory allocation, but is otherwise an opaque pointer.
+    #[inline]
+    pub fn spilled_storage(&self) -> Option<*const ()> {
+        None
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+impl<T> Storage<T> {
+    #[inline]
+    fn from_data(data: NonNull<()>) -> Storage<T> {
+        let data = data.as_ptr() as usize;
+
+        let len = (data & TAG_MASK) >> TAG_SHIFT;
+        let mut ptr = data & PTR_MASK;
+
+        if (ptr & PTR_HIGH) == PTR_HIGH {
+            // Canonical linear addresses on x86_64 are sign extended from
+            // bit 48.
+            ptr |= TAG_MASK;
+        }
+
+        if len < TAG_LIMIT {
+            Storage::Inline(ptr as *mut T, len)
+        } else {
+            Storage::Spilled(ptr as *mut Box<[T]>)
+        }
+    }
+
+    #[inline]
+    fn into_data(self) -> NonNull<()> {
+        let data = match self {
+            Storage::Inline(ptr, len) => {
+                (len << TAG_SHIFT) | ((ptr as usize) & PTR_MASK)
+            }
+            Storage::Spilled(ptr) => {
+                TAG_MASK | ((ptr as usize) & PTR_MASK)
+            }
+        };
+        unsafe {
+            NonNull::new_unchecked(data as *mut _)
+        }
+    }
+}
+
+impl<T> From<Box<[T]>> for ThinBoxedSlice<T> {
+    fn from(value: Box<[T]>) -> ThinBoxedSlice<T> {
+        let ptr = Box::into_raw(value);
+        unsafe {
+            ThinBoxedSlice::from_raw(ptr)
+        }
+    }
+}
+
+impl<T> Into<Box<[T]>> for ThinBoxedSlice<T> {
+    fn into(self) -> Box<[T]> {
+        let ptr = ThinBoxedSlice::into_raw(self);
+        unsafe {
+            Box::from_raw(ptr)
+        }
+    }
+}
+
+unsafe impl<T: Send> Send for ThinBoxedSlice<T> {}
+unsafe impl<T: Sync> Sync for ThinBoxedSlice<T> {}
+
+#[cfg(target_arch = "x86_64")]
+impl<T> Drop for ThinBoxedSlice<T> {
+    fn drop(&mut self) {
+        let _ = Into::<Box<[T]>>::into(
+            ThinBoxedSlice {
+                data: self.data.clone(),
+                _phantom: PhantomData,
+            }
+        );
+    }
+}
+
+impl<T: Clone> Clone for ThinBoxedSlice<T> {
+    #[cfg(target_arch = "x86_64")]
+    fn clone(&self) -> Self {
+        unsafe {
+            match self.storage() {
+                Storage::Inline(ptr, len) => {
+                    slice::from_raw_parts_mut(ptr, len)
+                        .to_vec()
+                        .into_boxed_slice()
+                        .into()
+                }
+                Storage::Spilled(ptr) => {
+                    (*ptr).clone().into()
+                }
+            }
+        }
+    }
+
+    #[cfg(not(target_arch = "x86_64"))]
+    fn clone(&self) -> Self {
+        ThinBoxedSlice {
+            data: self.data.clone(),
+        }
+    }
+}
+
+impl<T> AsRef<[T]> for ThinBoxedSlice<T> {
+    fn as_ref(&self) -> &[T] {
+        &**self
+    }
+}
+
+impl<T> AsMut<[T]> for ThinBoxedSlice<T> {
+    fn as_mut(&mut self) -> &mut [T] {
+        &mut **self
+    }
+}
+
+impl<T> Deref for ThinBoxedSlice<T> {
+    type Target = [T];
+
+    #[cfg(target_arch = "x86_64")]
+    fn deref(&self) -> &[T] {
+        unsafe {
+            match self.storage() {
+                Storage::Inline(ptr, len) => {
+                    slice::from_raw_parts(ptr, len)
+                }
+                Storage::Spilled(ptr) => {
+                    &**ptr
+                }
+            }
+        }
+    }
+
+    #[cfg(not(target_arch = "x86_64"))]
+    fn deref(&self) -> &[T] {
+        &*self.data
+    }
+}
+
+impl<T> DerefMut for ThinBoxedSlice<T> {
+    #[cfg(target_arch = "x86_64")]
+    fn deref_mut(&mut self) -> &mut [T] {
+        unsafe {
+            match self.storage() {
+                Storage::Inline(ptr, len) => {
+                    slice::from_raw_parts_mut(ptr, len)
+                }
+                Storage::Spilled(ptr) => {
+                    &mut **ptr
+                }
+            }
+        }
+    }
+
+    #[cfg(not(target_arch = "x86_64"))]
+    fn deref_mut(&mut self) -> &mut [T] {
+        &mut *self.data
+    }
+}
+
+impl<T> Default for ThinBoxedSlice<T> {
+    fn default() -> Self {
+        Box::<[T]>::default().into()
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for ThinBoxedSlice<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+impl<T: Eq> Eq for ThinBoxedSlice<T> {}
+
+impl<T: Hash> Hash for ThinBoxedSlice<T> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        (**self).hash(state);
+    }
+}
+
+impl<T: PartialEq> PartialEq for ThinBoxedSlice<T> {
+    #[inline]
+    fn eq(&self, other: &ThinBoxedSlice<T>) -> bool {
+        PartialEq::eq(&**self, &**other)
+    }
+    #[inline]
+    fn ne(&self, other: &ThinBoxedSlice<T>) -> bool {
+        PartialEq::ne(&**self, &**other)
+    }
+}
+
+impl<T: PartialOrd> PartialOrd for ThinBoxedSlice<T> {
+    #[inline]
+    fn partial_cmp(&self, other: &ThinBoxedSlice<T>) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&**self, &**other)
+    }
+    #[inline]
+    fn lt(&self, other: &ThinBoxedSlice<T>) -> bool {
+        PartialOrd::lt(&**self, &**other)
+    }
+    #[inline]
+    fn le(&self, other: &ThinBoxedSlice<T>) -> bool {
+        PartialOrd::le(&**self, &**other)
+    }
+    #[inline]
+    fn ge(&self, other: &ThinBoxedSlice<T>) -> bool {
+        PartialOrd::ge(&**self, &**other)
+    }
+    #[inline]
+    fn gt(&self, other: &ThinBoxedSlice<T>) -> bool {
+        PartialOrd::gt(&**self, &**other)
+    }
+}
+
+impl<T> fmt::Pointer for ThinBoxedSlice<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let ptr = &**self;
+        fmt::Pointer::fmt(&ptr, f)
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+#[test]
+fn test_spilled_storage() {
+    let x = ThinBoxedSlice::from(vec![0; TAG_LIMIT - 1].into_boxed_slice());
+    assert!(x.spilled_storage().is_none());
+
+    let x = ThinBoxedSlice::from(vec![0; TAG_LIMIT].into_boxed_slice());
+    assert!(x.spilled_storage().is_some());
+}
+
+#[cfg(target_arch = "x86_64")]
+#[test]
+fn test_from_raw_large() {
+    let mut vec = vec![0; TAG_LIMIT];
+    vec[123] = 456;
+
+    let ptr = Box::into_raw(vec.into_boxed_slice());
+    let x = unsafe { ThinBoxedSlice::from_raw(ptr) };
+    assert_eq!(x[123], 456);
+}
+
+#[cfg(target_arch = "x86_64")]
+#[test]
+fn test_into_raw_large() {
+    let mut vec = vec![0; TAG_LIMIT];
+    vec[123] = 456;
+
+    let x = ThinBoxedSlice::from(vec.into_boxed_slice());
+    let ptr = ThinBoxedSlice::into_raw(x);
+    let y = unsafe { Box::from_raw(ptr) };
+    assert_eq!(y[123], 456);
+}
+
+#[cfg(target_arch = "x86_64")]
+#[test]
+fn test_leak_large() {
+    let mut vec = vec![0; TAG_LIMIT];
+    vec[123] = 456;
+
+    let x = ThinBoxedSlice::from(vec.into_boxed_slice());
+    let static_ref = ThinBoxedSlice::leak(x);
+    static_ref[123] *= 1000;
+    assert_eq!(static_ref[123], 456000);
+}