Skip to content
Permalink
Browse files

style: Introduce ArcSlice, a small wrapper over ThinArc but without a…

…n explicit header.

We could make the header PhantomData or something, but then we wouldn't be able
to bind to C++, since C++ doesn't have ZSTs. So add a canary instead to add a
runtime check of stuff being sane.

Differential Revision: https://phabricator.services.mozilla.com/D30133
  • Loading branch information...
emilio committed May 9, 2019
1 parent 2ed2151 commit 0d5c4481b8b5f96325260ee0ffc2b5f206c97548
@@ -784,6 +784,13 @@ pub struct ThinArc<H, T> {
phantom: PhantomData<(H, T)>,
}


impl<H: fmt::Debug, T: fmt::Debug> fmt::Debug for ThinArc<H, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.deref(), f)
}
}

unsafe impl<H: Sync + Send, T: Sync + Send> Send for ThinArc<H, T> {}
unsafe impl<H: Sync + Send, T: Sync + Send> Sync for ThinArc<H, T> {}

@@ -856,8 +863,12 @@ impl<H, T> ThinArc<H, T> {
}

/// Returns the address on the heap of the ThinArc itself -- not the T
/// within it -- for memory reporting.
///
/// within it -- for memory reporting, and bindings.
#[inline]
pub fn ptr(&self) -> *const c_void {
self.ptr.as_ptr() as *const ArcInner<T> as *const c_void
}

/// If this is a static ThinArc, this returns null.
#[inline]
pub fn heap_ptr(&self) -> *const c_void {
@@ -866,7 +877,7 @@ impl<H, T> ThinArc<H, T> {
if is_static {
ptr::null()
} else {
self.ptr.as_ptr() as *const ArcInner<T> as *const c_void
self.ptr()
}
}
}
@@ -188,6 +188,7 @@ pub use html5ever::Prefix;
#[cfg(feature = "servo")]
pub use servo_atoms::Atom;

pub use style_traits::arc_slice::ArcSlice;
pub use style_traits::owned_slice::OwnedSlice;

/// The CSS properties supported by the style system.
@@ -462,3 +462,17 @@ where
Ok(v.into_boxed_slice())
}
}

impl<T> ToAnimatedZero for crate::ArcSlice<T>
where
T: ToAnimatedZero,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
let v = self
.iter()
.map(|v| v.to_animated_zero())
.collect::<Result<Vec<_>, _>>()?;
Ok(crate::ArcSlice::from_iter(v.into_iter()))
}
}
@@ -0,0 +1,66 @@
/* 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 https://mozilla.org/MPL/2.0/. */

//! A thin atomically-reference-counted slice.

use servo_arc::ThinArc;
use std::mem;
use std::ops::Deref;
use std::ptr::NonNull;

/// A canary that we stash in ArcSlices.
///
/// Given we cannot use a zero-sized-type for the header, since well, C++
/// doesn't have zsts, and we want to use cbindgen for this type, we may as well
/// assert some sanity at runtime.
const ARC_SLICE_CANARY: u32 = 0xf3f3f3f3;

/// A wrapper type for a refcounted slice using ThinArc.
///
/// cbindgen:derive-eq=false
/// cbindgen:derive-neq=false
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq, ToShmem)]
pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u32, T>);

impl<T> Deref for ArcSlice<T> {
type Target = [T];

#[inline]
fn deref(&self) -> &Self::Target {
debug_assert_eq!(self.0.header.header, ARC_SLICE_CANARY);
&self.0.slice
}
}

/// The inner pointer of an ArcSlice<T>, to be sent via FFI.
/// The type of the pointer is a bit of a lie, we just want to preserve the type
/// but these pointers cannot be constructed outside of this crate, so we're
/// good.
#[repr(C)]
pub struct ForgottenArcSlicePtr<T>(NonNull<T>);

impl<T> ArcSlice<T> {
/// Creates an Arc for a slice using the given iterator to generate the
/// slice.
#[inline]
pub fn from_iter<I>(items: I) -> Self
where
I: Iterator<Item = T> + ExactSizeIterator,
{
ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items))
}

/// Creates a value that can be passed via FFI, and forgets this value
/// altogether.
#[inline]
#[allow(unsafe_code)]
pub fn forget(self) -> ForgottenArcSlicePtr<T> {
let ret = unsafe {
ForgottenArcSlicePtr(NonNull::new_unchecked(self.0.ptr() as *const _ as *mut _))
};
mem::forget(self);
ret
}
}
@@ -84,6 +84,7 @@ pub enum CSSPixel {}
// / hidpi_ratio => DeviceIndependentPixel
// / desktop_zoom => CSSPixel

pub mod arc_slice;
pub mod specified_value_info;
#[macro_use]
pub mod values;
@@ -4,6 +4,7 @@

//! Value information for devtools.

use crate::arc_slice::ArcSlice;
use servo_arc::Arc;
use std::ops::Range;
use std::sync::Arc as StdArc;
@@ -116,6 +117,7 @@ impl_generic_specified_value_info!(Option<T>);
impl_generic_specified_value_info!(Vec<T>);
impl_generic_specified_value_info!(Arc<T>);
impl_generic_specified_value_info!(StdArc<T>);
impl_generic_specified_value_info!(ArcSlice<T>);
impl_generic_specified_value_info!(Range<Idx>);

impl<T1, T2> SpecifiedValueInfo for (T1, T2)

0 comments on commit 0d5c448

Please sign in to comment.
You can’t perform that action at this time.