1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 //! A thin atomically-reference-counted slice. 6 7 use serde::de::{Deserialize, Deserializer}; 8 use serde::ser::{Serialize, Serializer}; 9 use servo_arc::ThinArc; 10 use std::ops::Deref; 11 use std::ptr::NonNull; 12 use std::{iter, mem}; 13 14 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf}; 15 16 /// A canary that we stash in ArcSlices. 17 /// 18 /// Given we cannot use a zero-sized-type for the header, since well, C++ 19 /// doesn't have zsts, and we want to use cbindgen for this type, we may as well 20 /// assert some sanity at runtime. 21 /// 22 /// We use an u64, to guarantee that we can use a single singleton for every 23 /// empty slice, even if the types they hold are aligned differently. 24 const ARC_SLICE_CANARY: u64 = 0xf3f3f3f3f3f3f3f3; 25 26 /// A wrapper type for a refcounted slice using ThinArc. 27 /// 28 /// cbindgen:derive-eq=false 29 /// cbindgen:derive-neq=false 30 #[repr(C)] 31 #[derive(Debug, Eq, PartialEq, ToShmem)] 32 pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u64, T>); 33 34 impl<T> Deref for ArcSlice<T> { 35 type Target = [T]; 36 37 #[inline] deref(&self) -> &Self::Target38 fn deref(&self) -> &Self::Target { 39 debug_assert_eq!(self.0.header.header, ARC_SLICE_CANARY); 40 &self.0.slice 41 } 42 } 43 44 impl<T> Clone for ArcSlice<T> { clone(&self) -> Self45 fn clone(&self) -> Self { 46 ArcSlice(self.0.clone()) 47 } 48 } 49 50 lazy_static! { 51 // ThinArc doesn't support alignments greater than align_of::<u64>. 52 static ref EMPTY_ARC_SLICE: ArcSlice<u64> = { 53 ArcSlice::from_iter_leaked(iter::empty()) 54 }; 55 } 56 57 impl<T> Default for ArcSlice<T> { 58 #[allow(unsafe_code)] default() -> Self59 fn default() -> Self { 60 debug_assert!( 61 mem::align_of::<T>() <= mem::align_of::<u64>(), 62 "Need to increase the alignment of EMPTY_ARC_SLICE" 63 ); 64 unsafe { 65 let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone(); 66 let empty: Self = mem::transmute(empty); 67 debug_assert_eq!(empty.len(), 0); 68 empty 69 } 70 } 71 } 72 73 impl<T: Serialize> Serialize for ArcSlice<T> { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 75 where 76 S: Serializer, 77 { 78 self.deref().serialize(serializer) 79 } 80 } 81 82 impl<'de, T: Deserialize<'de>> Deserialize<'de> for ArcSlice<T> { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,83 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 84 where 85 D: Deserializer<'de>, 86 { 87 let r = Vec::deserialize(deserializer)?; 88 Ok(ArcSlice::from_iter(r.into_iter())) 89 } 90 } 91 92 impl<T> ArcSlice<T> { 93 /// Creates an Arc for a slice using the given iterator to generate the 94 /// slice. 95 #[inline] from_iter<I>(items: I) -> Self where I: Iterator<Item = T> + ExactSizeIterator,96 pub fn from_iter<I>(items: I) -> Self 97 where 98 I: Iterator<Item = T> + ExactSizeIterator, 99 { 100 if items.len() == 0 { 101 return Self::default(); 102 } 103 ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items)) 104 } 105 106 /// Creates an Arc for a slice using the given iterator to generate the 107 /// slice, and marks the arc as intentionally leaked from the refcount 108 /// logging point of view. 109 #[inline] from_iter_leaked<I>(items: I) -> Self where I: Iterator<Item = T> + ExactSizeIterator,110 pub fn from_iter_leaked<I>(items: I) -> Self 111 where 112 I: Iterator<Item = T> + ExactSizeIterator, 113 { 114 let thin_arc = ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items); 115 thin_arc.with_arc(|a| a.mark_as_intentionally_leaked()); 116 ArcSlice(thin_arc) 117 } 118 119 /// Creates a value that can be passed via FFI, and forgets this value 120 /// altogether. 121 #[inline] 122 #[allow(unsafe_code)] forget(self) -> ForgottenArcSlicePtr<T>123 pub fn forget(self) -> ForgottenArcSlicePtr<T> { 124 let ret = unsafe { 125 ForgottenArcSlicePtr(NonNull::new_unchecked(self.0.ptr() as *const _ as *mut _)) 126 }; 127 mem::forget(self); 128 ret 129 } 130 131 /// Leaks an empty arc slice pointer, and returns it. Only to be used to 132 /// construct ArcSlices from FFI. 133 #[inline] leaked_empty_ptr() -> *mut std::os::raw::c_void134 pub fn leaked_empty_ptr() -> *mut std::os::raw::c_void { 135 let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone(); 136 let ptr = empty.0.ptr(); 137 std::mem::forget(empty); 138 ptr as *mut _ 139 } 140 141 /// Returns whether there's only one reference to this ArcSlice. is_unique(&self) -> bool142 pub fn is_unique(&self) -> bool { 143 self.0.with_arc(|arc| arc.is_unique()) 144 } 145 } 146 147 impl<T: MallocSizeOf> MallocUnconditionalSizeOf for ArcSlice<T> { 148 #[allow(unsafe_code)] unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize149 fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { 150 let mut size = unsafe { ops.malloc_size_of(self.0.heap_ptr()) }; 151 for el in self.iter() { 152 size += el.size_of(ops); 153 } 154 size 155 } 156 } 157 158 /// The inner pointer of an ArcSlice<T>, to be sent via FFI. 159 /// The type of the pointer is a bit of a lie, we just want to preserve the type 160 /// but these pointers cannot be constructed outside of this crate, so we're 161 /// good. 162 #[repr(C)] 163 pub struct ForgottenArcSlicePtr<T>(NonNull<T>); 164