Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stylo: Fuse ServoStyleContext and ServoComputedValues #17767

Merged
merged 16 commits into from Jul 18, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

stylo: Make Servo Arc types use ptr to T instead of ptr to ArcInner<T>

  • Loading branch information
Manishearth committed Jul 18, 2017
commit 74519cc1a7bdc5ff31921fc2e59b3cb697774efa
@@ -194,6 +194,30 @@ impl<T> Arc<T> {
p: NonZeroPtrMut::new(ptr as *mut ArcInner<T>),
}
}

/// Produce a pointer to the data that can be converted back
/// to an arc
pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, 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
}
}

impl<T: ?Sized> Arc<T> {
@@ -717,6 +741,7 @@ impl<H: Eq + 'static, T: Eq + 'static> Eq for ThinArc<H, 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
#[derive(Eq)]
pub struct RawOffsetArc<T: 'static> {
ptr: NonZeroPtrMut<T>,
}
@@ -733,7 +758,7 @@ impl<T: 'static> Deref for RawOffsetArc<T> {

impl<T: 'static> Clone for RawOffsetArc<T> {
fn clone(&self) -> Self {
RawOffsetArc::with_arc(self, |a| Arc::into_raw_offset(a.clone()))
Arc::into_raw_offset(self.clone_arc())
}
}

@@ -750,6 +775,16 @@ impl<T: fmt::Debug + 'static> fmt::Debug for RawOffsetArc<T> {
}
}

impl<T: PartialEq> PartialEq for RawOffsetArc<T> {
fn eq(&self, other: &RawOffsetArc<T>) -> bool {
*(*self) == *(*other)
}

fn ne(&self, other: &RawOffsetArc<T>) -> bool {
*(*self) != *(*other)
}
}

impl<T: 'static> RawOffsetArc<T> {
/// Temporarily converts |self| into a bonafide Arc and exposes it to the
/// provided callback. The refcount is not modified.
@@ -789,6 +824,17 @@ impl<T: 'static> RawOffsetArc<T> {
&mut *ret
}
}

/// Clone it as an Arc
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
pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, T> {
ArcBorrow(&**self)
}
}

impl<T: 'static> Arc<T> {
@@ -811,6 +857,62 @@ impl<T: 'static> Arc<T> {
}
}

/// A "borrowed Arc". This is a pointer to
/// a T that is known to have been allocated within an
/// Arc.
///
/// This is equivalent in guarantees to `&Arc<T>`, however it is
/// a bit more flexible. To obtain an `&Arc<T>` you must have
/// an Arc<T> instance somewhere pinned down until we're done with it.
///
/// However, Gecko hands 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.
///
/// ArcBorrow lets us deal with borrows of known-refcounted objects
/// without needing to worry about how they're actually stored.
#[derive(PartialEq, Eq)]
pub struct ArcBorrow<'a, T: 'a>(&'a T);

impl<'a, T> Copy for ArcBorrow<'a, T> {}
impl<'a, T> Clone for ArcBorrow<'a, T> {
fn clone(&self) -> Self {
*self
}
}

impl<'a, T> ArcBorrow<'a, T> {
pub fn clone_arc(&self) -> Arc<T> {
let arc = unsafe { Arc::from_raw(self.0) };
// addref it!
mem::forget(arc.clone());
arc
}

pub fn with_arc<F, U>(&self, f: F) -> U where F: FnOnce(&Arc<T>) -> U, T: 'static {
// Synthesize transient Arc, which never touches the refcount.
let transient = unsafe { NoDrop::new(Arc::from_raw(self.0)) };

// 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
}
}

impl<'a, T> Deref for ArcBorrow<'a, T> {
type Target = T;
fn deref(&self) -> &T {
&*self.0
}
}

#[cfg(test)]
mod tests {
use std::clone::Clone;
@@ -30,7 +30,7 @@ use std::fmt;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::Deref;
use stylearc::Arc;
use stylearc::{Arc, ArcBorrow};
use stylist::Stylist;
use thread_state;

@@ -360,15 +360,15 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
}

/// Get this element's style attribute.
fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>>;
fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>;

/// Unset the style attribute's dirty bit.
/// Servo doesn't need to manage ditry bit for style attribute.
fn unset_dirty_style_attribute(&self) {
}

/// Get this element's SMIL override declarations.
fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
fn get_smil_override(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
None
}

@@ -56,7 +56,7 @@ impl GeckoRestyleDamage {
let mut any_style_changed: bool = false;
let hint = unsafe {
bindings::Gecko_CalcStyleDifference(context,
new_style.as_borrowed_opt().unwrap(),
new_style.as_borrowed(),
&mut any_style_changed)
};
let change = if any_style_changed { StyleChange::Changed } else { StyleChange::Unchanged };
@@ -64,7 +64,7 @@ use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS;
use gecko_bindings::structs::nsIDocument_DocumentTheme as DocumentTheme;
use gecko_bindings::sugar::ownership::{HasArcFFI, HasSimpleFFI};
use gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasSimpleFFI};
use logical_geometry::WritingMode;
use media_queries::Device;
use properties::{ComputedValues, parse_style_attribute};
@@ -88,7 +88,7 @@ use std::mem;
use std::ops::DerefMut;
use std::ptr;
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use stylearc::Arc;
use stylearc::{Arc, ArcBorrow, RawOffsetArc};
use stylesheets::UrlExtraData;
use stylist::Stylist;

@@ -860,13 +860,15 @@ impl<'le> TElement for GeckoElement<'le> {
device.pres_context().mDocument.raw::<structs::nsIDocument>()
}

fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
if !self.may_have_style_attribute() {
return None;
}

let declarations = unsafe { Gecko_GetStyleAttrDeclarationBlock(self.0) };
declarations.map_or(None, |s| s.as_arc_opt())
let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
= declarations.and_then(|s| s.as_arc_opt());
declarations.map(|s| s.borrow_arc())
}

fn unset_dirty_style_attribute(&self) {
@@ -877,9 +879,11 @@ impl<'le> TElement for GeckoElement<'le> {
unsafe { Gecko_UnsetDirtyStyleAttr(self.0) };
}

fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
fn get_smil_override(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
let declarations = unsafe { Gecko_GetSMILOverrideDeclarationBlock(self.0) };
declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
= declarations.and_then(|s| s.as_arc_opt());
declarations.map(|s| s.borrow_arc())
}

fn get_animation_rule_by_cascade(&self, cascade_level: ServoCascadeLevel)
@@ -1098,9 +1102,9 @@ impl<'le> TElement for GeckoElement<'le> {
let computed_values =
computed_data.as_ref().map(|d| d.styles.primary());
let computed_values_opt =
computed_values.map(|v| *HasArcFFI::arc_as_borrowed(v));
computed_values.map(|v| v.as_borrowed());
let before_change_values =
before_change_style.as_ref().map(|v| *HasArcFFI::arc_as_borrowed(v));
before_change_style.as_ref().map(|v| v.as_borrowed());
unsafe {
Gecko_UpdateAnimations(self.0,
before_change_values,
@@ -1182,7 +1186,7 @@ impl<'le> TElement for GeckoElement<'le> {
};
let end_value = AnimationValue::arc_from_borrowed(&raw_end_value);
debug_assert!(end_value.is_some());
map.insert(property, end_value.unwrap().clone());
map.insert(property, end_value.unwrap().clone_arc());
}
map
}
@@ -1428,17 +1432,19 @@ impl<'le> PresentationalHintsSynthesizer for GeckoElement<'le> {
}
}
let declarations = unsafe { Gecko_GetHTMLPresentationAttrDeclarationBlock(self.0) };
let declarations = declarations.and_then(|s| s.as_arc_opt());
let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
= declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}
let declarations = unsafe { Gecko_GetExtraContentStyleDeclarations(self.0) };
let declarations = declarations.and_then(|s| s.as_arc_opt());
let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
= declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}

@@ -1458,20 +1464,22 @@ impl<'le> PresentationalHintsSynthesizer for GeckoElement<'le> {
Gecko_GetVisitedLinkAttrDeclarationBlock(self.0)
},
};
let declarations = declarations.and_then(|s| s.as_arc_opt());
let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>> =
declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}

let active = self.get_state().intersects(NonTSPseudoClass::Active.state_flag());
if active {
let declarations = unsafe { Gecko_GetActiveLinkAttrDeclarationBlock(self.0) };
let declarations = declarations.and_then(|s| s.as_arc_opt());
let declarations: Option<&RawOffsetArc<Locked<PropertyDeclarationBlock>>>
= declarations.and_then(|s| s.as_arc_opt());
if let Some(decl) = declarations {
hints.push(
ApplicableDeclarationBlock::from_declarations(Clone::clone(decl), ServoCascadeLevel::PresHints)
ApplicableDeclarationBlock::from_declarations(decl.clone_arc(), ServoCascadeLevel::PresHints)
);
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.