mirror of
https://github.com/servo/servo.git
synced 2025-06-27 18:43:40 +01:00
style: Remove some magic from the bindings
This simplifies a tiny bit our bindings in some places, and complicates it in others, but over all I think it's better. It requires a bit more manual code in the rust side to drop and cast the relevant pointers (which was done implicitly before), but it's a lot less magic than it used to be, and that's all autogenerated so consumers don't need to care about it. The set up is still not ideal. I don't like that we rely on destructors running in both sides of the FFI boundary, but that's for another day. This is the last usage of RawOffsetArc, so remove that. We now support proper Arc<> in structs (GridTemplateAreas uses it), so I don't think we'll need it any time soon. Differential Revision: https://phabricator.services.mozilla.com/D177905
This commit is contained in:
parent
e9bf977369
commit
d1046739fc
7 changed files with 320 additions and 472 deletions
|
@ -218,8 +218,6 @@ impl<T> Arc<T> {
|
|||
/// Convert the Arc<T> to a raw pointer, suitable for use across FFI
|
||||
///
|
||||
/// Note: This returns a pointer to the data T, which is offset in the allocation.
|
||||
///
|
||||
/// It is recommended to use RawOffsetArc for this.
|
||||
#[inline]
|
||||
pub fn into_raw(this: Self) -> *const T {
|
||||
let ptr = unsafe { &((*this.ptr()).data) as *const _ };
|
||||
|
@ -286,26 +284,6 @@ impl<T> Arc<T> {
|
|||
ArcBorrow(&**self)
|
||||
}
|
||||
|
||||
/// Temporarily converts |self| into a bonafide RawOffsetArc and exposes it to the
|
||||
/// provided callback. The refcount is not modified.
|
||||
#[inline(always)]
|
||||
pub fn with_raw_offset_arc<F, U>(&self, f: F) -> U
|
||||
where
|
||||
F: FnOnce(&RawOffsetArc<T>) -> U,
|
||||
{
|
||||
// Synthesize transient Arc, which never touches the refcount of the ArcInner.
|
||||
let transient = unsafe { NoDrop::new(Arc::into_raw_offset(ptr::read(self))) };
|
||||
|
||||
// Expose the transient Arc to the callback, which may clone it if it wants.
|
||||
let result = f(&transient);
|
||||
|
||||
// Forget the transient Arc to leave the refcount untouched.
|
||||
mem::forget(transient);
|
||||
|
||||
// Forward the result.
|
||||
result
|
||||
}
|
||||
|
||||
/// Returns the address on the heap of the Arc itself -- not the T within it -- for memory
|
||||
/// reporting.
|
||||
///
|
||||
|
@ -1100,149 +1078,6 @@ impl<H: PartialEq, T: PartialEq> PartialEq for ThinArc<H, T> {
|
|||
|
||||
impl<H: Eq, T: Eq> Eq for ThinArc<H, T> {}
|
||||
|
||||
/// An `Arc`, except it holds a pointer to the T instead of to the
|
||||
/// entire ArcInner. This struct is FFI-compatible.
|
||||
///
|
||||
/// ```text
|
||||
/// Arc<T> RawOffsetArc<T>
|
||||
/// | |
|
||||
/// v v
|
||||
/// ---------------------
|
||||
/// | RefCount | T (data) | [ArcInner<T>]
|
||||
/// ---------------------
|
||||
/// ```
|
||||
///
|
||||
/// This means that this is a direct pointer to
|
||||
/// its contained data (and can be read from by both C++ and Rust),
|
||||
/// but we can also convert it to a "regular" Arc<T> by removing the offset.
|
||||
///
|
||||
/// This is very useful if you have an Arc-containing struct shared between Rust and C++,
|
||||
/// and wish for C++ to be able to read the data behind the `Arc` without incurring
|
||||
/// an FFI call overhead.
|
||||
#[derive(Eq)]
|
||||
#[repr(C)]
|
||||
pub struct RawOffsetArc<T> {
|
||||
ptr: ptr::NonNull<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T: Sync + Send> Send for RawOffsetArc<T> {}
|
||||
unsafe impl<T: Sync + Send> Sync for RawOffsetArc<T> {}
|
||||
|
||||
impl<T> Deref for RawOffsetArc<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.ptr.as_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for RawOffsetArc<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
Arc::into_raw_offset(self.clone_arc())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for RawOffsetArc<T> {
|
||||
fn drop(&mut self) {
|
||||
let _ = Arc::from_raw_offset(RawOffsetArc { ptr: self.ptr });
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for RawOffsetArc<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for RawOffsetArc<T> {
|
||||
fn eq(&self, other: &RawOffsetArc<T>) -> bool {
|
||||
*(*self) == *(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RawOffsetArc<T> {
|
||||
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
|
||||
/// provided callback. The refcount is not modified.
|
||||
#[inline]
|
||||
pub fn with_arc<F, U>(&self, f: F) -> U
|
||||
where
|
||||
F: FnOnce(&Arc<T>) -> U,
|
||||
{
|
||||
// Synthesize transient Arc, which never touches the refcount of the ArcInner.
|
||||
let transient = unsafe { NoDrop::new(Arc::from_raw(self.ptr.as_ptr())) };
|
||||
|
||||
// Expose the transient Arc to the callback, which may clone it if it wants.
|
||||
let result = f(&transient);
|
||||
|
||||
// Forget the transient Arc to leave the refcount untouched.
|
||||
// XXXManishearth this can be removed when unions stabilize,
|
||||
// since then NoDrop becomes zero overhead
|
||||
mem::forget(transient);
|
||||
|
||||
// Forward the result.
|
||||
result
|
||||
}
|
||||
|
||||
/// If uniquely owned, provide a mutable reference
|
||||
/// Else create a copy, and mutate that
|
||||
///
|
||||
/// This is functionally the same thing as `Arc::make_mut`
|
||||
#[inline]
|
||||
pub fn make_mut(&mut self) -> &mut T
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
unsafe {
|
||||
// extract the RawOffsetArc as an owned variable
|
||||
let this = ptr::read(self);
|
||||
// treat it as a real Arc
|
||||
let mut arc = Arc::from_raw_offset(this);
|
||||
// obtain the mutable reference. Cast away the lifetime
|
||||
// This may mutate `arc`
|
||||
let ret = Arc::make_mut(&mut arc) as *mut _;
|
||||
// Store the possibly-mutated arc back inside, after converting
|
||||
// it to a RawOffsetArc again
|
||||
ptr::write(self, Arc::into_raw_offset(arc));
|
||||
&mut *ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Clone it as an `Arc`
|
||||
#[inline]
|
||||
pub fn clone_arc(&self) -> Arc<T> {
|
||||
RawOffsetArc::with_arc(self, |a| a.clone())
|
||||
}
|
||||
|
||||
/// Produce a pointer to the data that can be converted back
|
||||
/// to an `Arc`
|
||||
#[inline]
|
||||
pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, T> {
|
||||
ArcBorrow(&**self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Arc<T> {
|
||||
/// Converts an `Arc` into a `RawOffsetArc`. This consumes the `Arc`, so the refcount
|
||||
/// is not modified.
|
||||
#[inline]
|
||||
pub fn into_raw_offset(a: Self) -> RawOffsetArc<T> {
|
||||
unsafe {
|
||||
RawOffsetArc {
|
||||
ptr: ptr::NonNull::new_unchecked(Arc::into_raw(a) as *mut T),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `RawOffsetArc` into an `Arc`. This consumes the `RawOffsetArc`, so the refcount
|
||||
/// is not modified.
|
||||
#[inline]
|
||||
pub fn from_raw_offset(a: RawOffsetArc<T>) -> Self {
|
||||
let ptr = a.ptr.as_ptr();
|
||||
mem::forget(a);
|
||||
unsafe { Arc::from_raw(ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A "borrowed `Arc`". This is a pointer to
|
||||
/// a T that is known to have been allocated within an
|
||||
/// `Arc`.
|
||||
|
@ -1253,8 +1088,7 @@ impl<T> Arc<T> {
|
|||
/// It's also a direct pointer to `T`, so using this involves less pointer-chasing
|
||||
///
|
||||
/// However, C++ code may hand us refcounted things as pointers to T directly,
|
||||
/// so we have to conjure up a temporary `Arc` on the stack each time. The
|
||||
/// same happens for when the object is managed by a `RawOffsetArc`.
|
||||
/// so we have to conjure up a temporary `Arc` on the stack each time.
|
||||
///
|
||||
/// `ArcBorrow` lets us deal with borrows of known-refcounted objects
|
||||
/// without needing to worry about where the `Arc<T>` is.
|
||||
|
|
|
@ -131,7 +131,7 @@ impl Device {
|
|||
line_height,
|
||||
pres_context.map_or(std::ptr::null(), |pc| pc),
|
||||
vertical,
|
||||
font.gecko(),
|
||||
&**font,
|
||||
element.map_or(std::ptr::null(), |e| e.0)
|
||||
)
|
||||
});
|
||||
|
@ -231,7 +231,7 @@ impl Device {
|
|||
bindings::Gecko_GetFontMetrics(
|
||||
pc,
|
||||
vertical,
|
||||
font.gecko(),
|
||||
&**font,
|
||||
base_size,
|
||||
// we don't use the user font set in a media query
|
||||
!in_media_query,
|
||||
|
|
|
@ -900,7 +900,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
|
||||
let builder = &mut self.context.builder;
|
||||
let default_font_type = {
|
||||
let font = builder.get_font().gecko();
|
||||
let font = builder.get_font();
|
||||
|
||||
if !font.mFont.family.is_initial {
|
||||
return;
|
||||
|
@ -922,9 +922,8 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
default_font_type
|
||||
};
|
||||
|
||||
let font = builder.mutate_font().gecko_mut();
|
||||
// NOTE: Leaves is_initial untouched.
|
||||
font.mFont.family.families = FontFamily::generic(default_font_type).families.clone();
|
||||
builder.mutate_font().mFont.family.families = FontFamily::generic(default_font_type).families.clone();
|
||||
}
|
||||
|
||||
/// Prioritize user fonts if needed by pref.
|
||||
|
@ -943,7 +942,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
|
||||
let builder = &mut self.context.builder;
|
||||
let default_font_type = {
|
||||
let font = builder.get_font().gecko();
|
||||
let font = builder.get_font();
|
||||
|
||||
if font.mFont.family.is_system_font {
|
||||
return;
|
||||
|
@ -961,7 +960,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
}
|
||||
};
|
||||
|
||||
let font = builder.mutate_font().gecko_mut();
|
||||
let font = builder.mutate_font();
|
||||
font.mFont.family.families.prioritize_first_generic_or_prepend(default_font_type);
|
||||
}
|
||||
|
||||
|
@ -986,7 +985,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
},
|
||||
};
|
||||
|
||||
if font.gecko().mScriptUnconstrainedSize == new_size.computed_size {
|
||||
if font.mScriptUnconstrainedSize == new_size.computed_size {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1013,9 +1012,9 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
|
||||
let builder = &mut self.context.builder;
|
||||
let min_font_size = {
|
||||
let font = builder.get_font().gecko();
|
||||
let font = builder.get_font();
|
||||
let min_font_size = unsafe {
|
||||
bindings::Gecko_nsStyleFont_ComputeMinSize(font, builder.device.document())
|
||||
bindings::Gecko_nsStyleFont_ComputeMinSize(&**font, builder.device.document())
|
||||
};
|
||||
|
||||
if font.mFont.size.0 >= min_font_size {
|
||||
|
@ -1025,7 +1024,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
NonNegative(min_font_size)
|
||||
};
|
||||
|
||||
builder.mutate_font().gecko_mut().mFont.size = min_font_size;
|
||||
builder.mutate_font().mFont.size = min_font_size;
|
||||
}
|
||||
|
||||
/// <svg:text> is not affected by text zoom, and it uses a preshint to disable it. We fix up
|
||||
|
@ -1133,8 +1132,8 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
|
||||
let (new_size, new_unconstrained_size) = {
|
||||
let builder = &self.context.builder;
|
||||
let font = builder.get_font().gecko();
|
||||
let parent_font = builder.get_parent_font().gecko();
|
||||
let font = builder.get_font();
|
||||
let parent_font = builder.get_parent_font();
|
||||
|
||||
let delta = font.mMathDepth.saturating_sub(parent_font.mMathDepth);
|
||||
|
||||
|
@ -1195,7 +1194,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
)
|
||||
}
|
||||
};
|
||||
let font = self.context.builder.mutate_font().gecko_mut();
|
||||
let font = self.context.builder.mutate_font();
|
||||
font.mFont.size = NonNegative(new_size);
|
||||
font.mSize = NonNegative(new_size);
|
||||
font.mScriptUnconstrainedSize = NonNegative(new_unconstrained_size);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -401,7 +401,7 @@ pub mod system_font {
|
|||
bindings::Gecko_nsFont_InitSystem(
|
||||
system.as_mut_ptr(),
|
||||
*self,
|
||||
cx.style().get_font().gecko(),
|
||||
&**cx.style().get_font(),
|
||||
cx.device().document()
|
||||
);
|
||||
&mut *system.as_mut_ptr()
|
||||
|
|
|
@ -3098,14 +3098,9 @@ impl ComputedValues {
|
|||
self.rules.as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Returns the visited style, if any.
|
||||
pub fn visited_style(&self) -> Option<<&ComputedValues> {
|
||||
self.visited_style.as_deref()
|
||||
}
|
||||
|
||||
/// Returns the visited rules, if applicable.
|
||||
pub fn visited_rules(&self) -> Option<<&StrongRuleNode> {
|
||||
self.visited_style.as_ref().and_then(|s| s.rules.as_ref())
|
||||
self.visited_style().and_then(|s| s.rules.as_ref())
|
||||
}
|
||||
|
||||
/// Gets a reference to the custom properties map (if one exists).
|
||||
|
@ -3346,6 +3341,11 @@ impl ops::DerefMut for ComputedValues {
|
|||
|
||||
#[cfg(feature = "servo")]
|
||||
impl ComputedValuesInner {
|
||||
/// Returns the visited style, if any.
|
||||
pub fn visited_style(&self) -> Option<<&ComputedValues> {
|
||||
self.visited_style.as_deref()
|
||||
}
|
||||
|
||||
% for style_struct in data.active_style_structs():
|
||||
/// Clone the ${style_struct.name} struct.
|
||||
#[inline]
|
||||
|
@ -3359,12 +3359,6 @@ impl ComputedValuesInner {
|
|||
&self.${style_struct.ident}
|
||||
}
|
||||
|
||||
/// Gets an immutable reference to the refcounted value that wraps
|
||||
/// `${style_struct.name}`.
|
||||
pub fn ${style_struct.name_lower}_arc(&self) -> &Arc<style_structs::${style_struct.name}> {
|
||||
&self.${style_struct.ident}
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the ${style_struct.name} struct.
|
||||
#[inline]
|
||||
pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
|
||||
|
@ -3563,24 +3557,10 @@ impl ComputedValuesInner {
|
|||
}
|
||||
}
|
||||
|
||||
% if engine == "gecko":
|
||||
pub use crate::servo_arc::RawOffsetArc as BuilderArc;
|
||||
/// Clone an arc, returning a regular arc
|
||||
fn clone_arc<T: 'static>(x: &BuilderArc<T>) -> Arc<T> {
|
||||
Arc::from_raw_offset(x.clone())
|
||||
}
|
||||
% else:
|
||||
pub use crate::servo_arc::Arc as BuilderArc;
|
||||
/// Clone an arc, returning a regular arc
|
||||
fn clone_arc<T: 'static>(x: &BuilderArc<T>) -> Arc<T> {
|
||||
x.clone()
|
||||
}
|
||||
% endif
|
||||
|
||||
/// A reference to a style struct of the parent, or our own style struct.
|
||||
pub enum StyleStructRef<'a, T: 'static> {
|
||||
/// A borrowed struct from the parent, for example, for inheriting style.
|
||||
Borrowed(&'a BuilderArc<T>),
|
||||
Borrowed(&'a T),
|
||||
/// An owned struct, that we've already mutated.
|
||||
Owned(UniqueArc<T>),
|
||||
/// Temporarily vacated, will panic if accessed
|
||||
|
@ -3595,7 +3575,7 @@ where
|
|||
/// borrowed value, or returning the owned one.
|
||||
pub fn mutate(&mut self) -> &mut T {
|
||||
if let StyleStructRef::Borrowed(v) = *self {
|
||||
*self = StyleStructRef::Owned(UniqueArc::new((**v).clone()));
|
||||
*self = StyleStructRef::Owned(UniqueArc::new(v.clone()));
|
||||
}
|
||||
|
||||
match *self {
|
||||
|
@ -3614,8 +3594,8 @@ where
|
|||
pub fn ptr_eq(&self, struct_to_copy_from: &T) -> bool {
|
||||
match *self {
|
||||
StyleStructRef::Owned(..) => false,
|
||||
StyleStructRef::Borrowed(arc) => {
|
||||
&**arc as *const T == struct_to_copy_from as *const T
|
||||
StyleStructRef::Borrowed(s) => {
|
||||
s as *const T == struct_to_copy_from as *const T
|
||||
}
|
||||
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||
}
|
||||
|
@ -3632,7 +3612,7 @@ where
|
|||
|
||||
match inner {
|
||||
StyleStructRef::Owned(arc) => arc,
|
||||
StyleStructRef::Borrowed(arc) => UniqueArc::new((**arc).clone()),
|
||||
StyleStructRef::Borrowed(s) => UniqueArc::new(s.clone()),
|
||||
StyleStructRef::Vacated => panic!("Accessed vacated style struct"),
|
||||
}
|
||||
}
|
||||
|
@ -3658,7 +3638,8 @@ where
|
|||
pub fn build(self) -> Arc<T> {
|
||||
match self {
|
||||
StyleStructRef::Owned(v) => v.shareable(),
|
||||
StyleStructRef::Borrowed(v) => clone_arc(v),
|
||||
// SAFETY: We know all style structs are arc-allocated.
|
||||
StyleStructRef::Borrowed(v) => unsafe { Arc::from_raw_addrefed(v) },
|
||||
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||
}
|
||||
}
|
||||
|
@ -3670,7 +3651,7 @@ impl<'a, T: 'a> ops::Deref for StyleStructRef<'a, T> {
|
|||
fn deref(&self) -> &T {
|
||||
match *self {
|
||||
StyleStructRef::Owned(ref v) => &**v,
|
||||
StyleStructRef::Borrowed(v) => &**v,
|
||||
StyleStructRef::Borrowed(v) => v,
|
||||
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
|
||||
}
|
||||
}
|
||||
|
@ -3773,9 +3754,9 @@ impl<'a> StyleBuilder<'a> {
|
|||
visited_style: None,
|
||||
% for style_struct in data.active_style_structs():
|
||||
% if style_struct.inherited:
|
||||
${style_struct.ident}: StyleStructRef::Borrowed(inherited_style.${style_struct.name_lower}_arc()),
|
||||
${style_struct.ident}: StyleStructRef::Borrowed(inherited_style.get_${style_struct.name_lower}()),
|
||||
% else:
|
||||
${style_struct.ident}: StyleStructRef::Borrowed(reset_style.${style_struct.name_lower}_arc()),
|
||||
${style_struct.ident}: StyleStructRef::Borrowed(reset_style.get_${style_struct.name_lower}()),
|
||||
% endif
|
||||
% endfor
|
||||
}
|
||||
|
@ -3813,7 +3794,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
visited_style: None,
|
||||
% for style_struct in data.active_style_structs():
|
||||
${style_struct.ident}: StyleStructRef::Borrowed(
|
||||
style_to_derive_from.${style_struct.name_lower}_arc()
|
||||
style_to_derive_from.get_${style_struct.name_lower}()
|
||||
),
|
||||
% endfor
|
||||
}
|
||||
|
@ -3824,7 +3805,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
% for style_struct in data.active_style_structs():
|
||||
% if not style_struct.inherited:
|
||||
self.${style_struct.ident} =
|
||||
StyleStructRef::Borrowed(style.${style_struct.name_lower}_arc());
|
||||
StyleStructRef::Borrowed(style.get_${style_struct.name_lower}());
|
||||
% endif
|
||||
% endfor
|
||||
}
|
||||
|
@ -3991,7 +3972,7 @@ impl<'a> StyleBuilder<'a> {
|
|||
/// Reset the current `${style_struct.name}` style to its default value.
|
||||
pub fn reset_${style_struct.name_lower}_struct(&mut self) {
|
||||
self.${style_struct.ident} =
|
||||
StyleStructRef::Borrowed(self.reset_style.${style_struct.name_lower}_arc());
|
||||
StyleStructRef::Borrowed(self.reset_style.get_${style_struct.name_lower}());
|
||||
}
|
||||
% endfor
|
||||
<% del style_struct %>
|
||||
|
|
|
@ -775,13 +775,13 @@ impl FontSizeKeyword {
|
|||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
fn to_length(&self, cx: &Context) -> NonNegativeLength {
|
||||
let gecko_font = cx.style().get_font().gecko();
|
||||
let family = &gecko_font.mFont.family.families;
|
||||
let font = cx.style().get_font();
|
||||
let family = &font.mFont.family.families;
|
||||
let generic = family
|
||||
.single_generic()
|
||||
.unwrap_or(computed::GenericFontFamily::None);
|
||||
let base_size = unsafe {
|
||||
Atom::with(gecko_font.mLanguage.mRawPtr, |language| {
|
||||
Atom::with(font.mLanguage.mRawPtr, |language| {
|
||||
cx.device().base_size_for_generic(language, generic)
|
||||
})
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue