Bug 1367904 - Part 4: stylo: Replace real ComputedValues with bindgenned ComputedValues2; r?bholley
MozReview-Commit-ID: GRkycXueUVr
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -62,16 +62,22 @@ struct nsMediaFeature;
struct nsStyleList;
struct nsStyleImage;
struct nsStyleGradientStop;
class nsStyleGradient;
class nsStyleCoord;
struct nsStyleDisplay;
class nsXBLBinding;
+namespace mozilla {
+ #define STYLE_STRUCT(name_, checkdata_cb_) struct Gecko##name_ {nsStyle##name_ gecko;};
+ #include "nsStyleStructList.h"
+ #undef STYLE_STRUCT
+}
+
#define NS_DECL_THREADSAFE_FFI_REFCOUNTING(class_, name_) \
void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr); \
void Gecko_Release##name_##ArbitraryThread(class_* aPtr);
#define NS_IMPL_THREADSAFE_FFI_REFCOUNTING(class_, name_) \
static_assert(class_::HasThreadSafeRefCnt::value, \
"NS_DECL_THREADSAFE_FFI_REFCOUNTING can only be used with " \
"classes that have thread-safe refcounting"); \
void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr) \
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -309,17 +309,19 @@ opaque-types = [
]
mapped-generic-types = [
{ generic = true, gecko = "mozilla::ServoUnsafeCell", servo = "::std::cell::UnsafeCell" },
{ generic = true, gecko = "mozilla::ServoCell", servo = "::std::cell::Cell" },
{ generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
{ generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
{ generic = false, gecko = "mozilla::ServoFontComputationData", servo = "::properties::FontComputationData" },
{ generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::stylearc::Arc<::custom_properties::CustomPropertiesMap>>" },
+ { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
{ generic = false, gecko = "mozilla::ServoVisitedStyle", servo = "Option<::stylearc::Arc<ServoComputedValues2>>" },
+ { generic = false, gecko = "mozilla::ServoComputedValueFlags", servo = "::properties::computed_value_flags::ComputedValueFlags" },
{ generic = true, gecko = "mozilla::ServoRawOffsetArc", servo = "::stylearc::RawOffsetArc" },
]
fixups = [
{ pat = "root::nsString", rep = "::nsstring::nsStringRepr" },
]
[bindings]
headers = ["mozilla/ServoBindings.h"]
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -137,41 +137,66 @@ struct ServoFontComputationData {
uint32_t mFour;
uint32_t mFour2;
};
struct ServoCustomPropertiesMap {
uintptr_t mPtr;
};
+struct ServoRuleNode {
+ uintptr_t mPtr;
+};
+
struct ServoVisitedStyle {
uintptr_t mPtr;
};
template <typename T>
struct ServoRawOffsetArc {
T* mPtr;
};
+struct ServoComputedValueFlags {
+ uint8_t mFlags;
+};
+
+#define STYLE_STRUCT(name_, checkdata_cb_) struct Gecko##name_;
+#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
+#include "nsStyleStructList.h"
+#undef STYLE_STRUCT
+#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
+
+
/**
* We want C++ to be abe to read the style struct fields of ComputedValues
* so we define this type on the C++ side and use the bindgenned version
* on the Rust side.
*
* C++ just sees pointers and opaque types here, so bindgen will attempt to generate a Copy
* impl. This will fail because the bindgenned version contains owned types. Opt out.
*
* <div rustbindgen nocopy></div>
*/
struct ServoComputedValues2 {
-#define STYLE_STRUCT(name_, checkdata_cb_) ServoRawOffsetArc<nsStyle##name_> name_;
+#define STYLE_STRUCT(name_, checkdata_cb_) ServoRawOffsetArc<Gecko##name_> name_;
+ #define STYLE_STRUCT_LIST_IGNORE_VARIABLES
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
+ #undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
ServoCustomPropertiesMap custom_properties;
ServoWritingMode writing_mode;
ServoFontComputationData font_computation_data;
+ /// The rule node representing the ordered list of rules matched for this
+ /// node. Can be None for default values and text nodes. This is
+ /// essentially an optimization to avoid referencing the root rule node.
+ ServoRuleNode rules;
+ /// The element's computed values if visited, only computed if there's a
+ /// relevant link for this element. A element's "relevant link" is the
+ /// element being matched if it is a link or the nearest ancestor link.
ServoVisitedStyle visited_style;
+ ServoComputedValueFlags flags;
~ServoComputedValues2() {} // do nothing, but prevent Copy from being impl'd by bindgen
};
} // namespace mozilla
#endif // mozilla_ServoTypes_h
--- a/layout/style/generate-stylestructlist.py
+++ b/layout/style/generate-stylestructlist.py
@@ -83,20 +83,24 @@ for i in range(count):
print("Resolved items:", " ".join(resolved_items), file=sys.stderr)
unsolved_items = [name for _, name, _, _ in STYLE_STRUCTS
if name not in resolved_items]
print("There exist cyclic dependencies between " +
"the following structs:", " ".join(unsolved_items), file=sys.stderr)
exit(1)
def printEntry(header, i):
+ if STYLE_STRUCTS[i][1] == "Variables":
+ print("#ifndef STYLE_STRUCT_LIST_IGNORE_VARIABLES", file=header)
print("STYLE_STRUCT_%s(%s, %s)" % STYLE_STRUCTS[i][:3], file=header)
for dep in STYLE_STRUCTS[i][3]:
print("STYLE_STRUCT_DEP(%s)" % (dep,), file=header)
print("STYLE_STRUCT_END()", file=header)
+ if STYLE_STRUCTS[i][1] == "Variables":
+ print("#endif", file=header)
HEADER = """/* THIS FILE IS AUTOGENERATED BY generate-stylestructlist.py - DO NOT EDIT */
// IWYU pragma: private, include "nsStyleStructFwd.h"
/*
* list of structs that contain the data provided by nsStyleContext, the
* internal API for computed style data for an element
--- a/servo/components/servo_arc/lib.rs
+++ b/servo/components/servo_arc/lib.rs
@@ -766,29 +766,49 @@ impl<T: 'static> RawOffsetArc<T> {
// 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
+ 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
+ }
+ }
}
impl<T: 'static> 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> {
RawOffsetArc {
ptr: NonZeroPtrMut::new(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.ptr();
mem::forget(a);
unsafe { Arc::from_raw(ptr) }
}
}
#[cfg(test)]
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -53,52 +53,49 @@ use gecko::values::GeckoStyleCoordConver
use gecko::values::round_border_to_device_pixels;
use logical_geometry::WritingMode;
use media_queries::Device;
use properties::animated_properties::TransitionProperty;
use properties::computed_value_flags::ComputedValueFlags;
use properties::{longhands, FontComputationData, Importance, LonghandId};
use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
use rule_tree::StrongRuleNode;
-use std::fmt::{self, Debug};
use std::mem::{forget, transmute, zeroed};
use std::ptr;
-use stylearc::Arc;
+use stylearc::{Arc, RawOffsetArc};
use std::cmp;
use values::{Auto, CustomIdent, Either, KeyframesName};
use values::computed::ToComputedValue;
use values::computed::effects::{BoxShadow, Filter, SimpleShadow};
use values::specified::length::Percentage;
use computed_values::border_style;
pub mod style_structs {
% for style_struct in data.style_structs:
pub use super::${style_struct.gecko_struct_name} as ${style_struct.name};
% endfor
}
-// FIXME(emilio): Unify both definitions, since they're equal now.
-#[derive(Clone)]
-pub struct ComputedValues {
- % for style_struct in data.style_structs:
- ${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
- % endfor
- custom_properties: Option<Arc<CustomPropertiesMap>>,
- pub writing_mode: WritingMode,
- pub font_computation_data: FontComputationData,
- pub flags: ComputedValueFlags,
-
- /// The rule node representing the ordered list of rules matched for this
- /// node. Can be None for default values and text nodes. This is
- /// essentially an optimization to avoid referencing the root rule node.
- pub rules: Option<StrongRuleNode>,
- /// The element's computed values if visited, only computed if there's a
- /// relevant link for this element. A element's "relevant link" is the
- /// element being matched if it is a link or the nearest ancestor link.
- visited_style: Option<Arc<ComputedValues>>,
+
+pub use ::gecko_bindings::structs::mozilla::ServoComputedValues2 as ComputedValues;
+
+impl Clone for ComputedValues {
+ fn clone(&self) -> Self {
+ ComputedValues {
+ % for style_struct in data.style_structs:
+ ${style_struct.gecko_name}: self.${style_struct.gecko_name}.clone(),
+ % endfor
+ custom_properties: self.custom_properties.clone(),
+ writing_mode: self.writing_mode.clone(),
+ font_computation_data: self.font_computation_data.clone(),
+ flags: self.flags.clone(),
+ rules: self.rules.clone(),
+ visited_style: self.visited_style.clone(),
+ }
+ }
}
impl ComputedValues {
pub fn new(custom_properties: Option<Arc<CustomPropertiesMap>>,
writing_mode: WritingMode,
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
flags: ComputedValueFlags,
rules: Option<StrongRuleNode>,
@@ -110,31 +107,31 @@ impl ComputedValues {
ComputedValues {
custom_properties,
writing_mode,
font_computation_data: FontComputationData::new(font_size_keyword),
flags,
rules,
visited_style: visited_style,
% for style_struct in data.style_structs:
- ${style_struct.ident},
+ ${style_struct.gecko_name}: Arc::into_raw_offset(${style_struct.ident}),
% endfor
}
}
pub fn default_values(pres_context: RawGeckoPresContextBorrowed) -> Arc<Self> {
Arc::new(ComputedValues {
custom_properties: None,
writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious
font_computation_data: FontComputationData::default_values(),
flags: ComputedValueFlags::empty(),
rules: None,
visited_style: None,
% for style_struct in data.style_structs:
- ${style_struct.ident}: style_structs::${style_struct.name}::default(pres_context),
+ ${style_struct.gecko_name}: Arc::into_raw_offset(style_structs::${style_struct.name}::default(pres_context)),
% endfor
})
}
#[inline]
pub fn is_display_contents(&self) -> bool {
self.get_box().clone_display() == longhands::display::computed_value::T::contents
}
@@ -144,30 +141,31 @@ impl ComputedValues {
#[inline]
pub fn ineffective_content_property(&self) -> bool {
self.get_counters().ineffective_content_property()
}
% for style_struct in data.style_structs:
#[inline]
pub fn clone_${style_struct.name_lower}(&self) -> Arc<style_structs::${style_struct.name}> {
- self.${style_struct.ident}.clone()
+ Arc::from_raw_offset(self.${style_struct.gecko_name}.clone())
}
#[inline]
pub fn get_${style_struct.name_lower}(&self) -> &style_structs::${style_struct.name} {
- &self.${style_struct.ident}
- }
-
- pub fn ${style_struct.name_lower}_arc(&self) -> &Arc<style_structs::${style_struct.name}> {
- &self.${style_struct.ident}
+ &self.${style_struct.gecko_name}
+ }
+
+
+ pub fn ${style_struct.name_lower}_arc(&self) -> &RawOffsetArc<style_structs::${style_struct.name}> {
+ &self.${style_struct.gecko_name}
}
#[inline]
pub fn mutate_${style_struct.name_lower}(&mut self) -> &mut style_structs::${style_struct.name} {
- Arc::make_mut(&mut self.${style_struct.ident})
+ RawOffsetArc::make_mut(&mut self.${style_struct.gecko_name})
}
% endfor
/// Gets a reference to the rule node. Panic if no rule node exists.
pub fn rules(&self) -> &StrongRuleNode {
self.rules.as_ref().unwrap()
}
@@ -233,19 +231,17 @@ impl ComputedValues {
% endfor
PropertyDeclarationId::Custom(_name) => unimplemented!(),
_ => unimplemented!()
}
}
}
<%def name="declare_style_struct(style_struct)">
-pub struct ${style_struct.gecko_struct_name} {
- gecko: ${style_struct.gecko_ffi_name},
-}
+pub use ::gecko_bindings::structs::mozilla::Gecko${style_struct.gecko_name} as ${style_struct.gecko_struct_name};
impl ${style_struct.gecko_struct_name} {
pub fn gecko(&self) -> &${style_struct.gecko_ffi_name} {
&self.gecko
}
pub fn gecko_mut(&mut self) -> &mut ${style_struct.gecko_ffi_name} {
&mut self.gecko
}
}
@@ -732,30 +728,16 @@ impl Clone for ${style_struct.gecko_stru
unsafe {
let mut result = ${style_struct.gecko_struct_name} { gecko: zeroed() };
Gecko_CopyConstruct_${style_struct.gecko_ffi_name}(&mut result.gecko, &self.gecko);
result
}
}
}
-// FIXME(bholley): Make bindgen generate Debug for all types.
-%if style_struct.gecko_ffi_name in ("nsStyle" + x for x in "Border Display List Background Font SVGReset".split()):
-impl Debug for ${style_struct.gecko_struct_name} {
- // FIXME(bholley): Generate this.
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Gecko style struct: ${style_struct.gecko_struct_name}")
- }
-}
-%else:
-impl Debug for ${style_struct.gecko_struct_name} {
- // FIXME(bholley): Generate this.
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.gecko.fmt(f) }
-}
-%endif
</%def>
<%def name="impl_simple_type_with_conversion(ident, gecko_ffi_name=None)">
<%
if gecko_ffi_name is None:
gecko_ffi_name = "m" + to_camel_case(ident)
%>
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -2232,24 +2232,16 @@ impl ComputedValues {
.and_then(|map| map.get_computed_value(name))
.map(|value| value.to_css_string())
.unwrap_or(String::new())
}
}
}
}
-// We manually implement Debug for ComputedValues so that we can avoid the
-// verbose stringification of every property and instead focus on a few values.
-impl fmt::Debug for ComputedValues {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "ComputedValues {{ rules: {:?}, .. }}", self.rules)
- }
-}
-
/// Return a WritingMode bitflags from the relevant CSS properties.
pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> WritingMode {
use logical_geometry;
let mut flags = WritingMode::empty();
match inheritedbox_style.clone_direction() {
computed_values::direction::T::ltr => {},
computed_values::direction::T::rtl => {
flags.insert(logical_geometry::FLAG_RTL);
@@ -2291,20 +2283,34 @@ pub fn get_writing_mode(inheritedbox_sty
flags.insert(logical_geometry::FLAG_SIDEWAYS);
},
}
}
% endif
flags
}
+% if product == "gecko":
+ pub use ::stylearc::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 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 Arc<T>),
+ Borrowed(&'a BuilderArc<T>),
/// An owned struct, that we've already mutated.
Owned(UniqueArc<T>),
/// Temporarily vacated, will panic if accessed
Vacated,
}
impl<'a, T: 'a> StyleStructRef<'a, T>
where T: Clone,
@@ -2355,17 +2361,17 @@ impl<'a, T: 'a> StyleStructRef<'a, T>
}
}
/// Returns an `Arc` to the internal struct, constructing one if
/// appropriate.
pub fn build(self) -> Arc<T> {
match self {
StyleStructRef::Owned(v) => v.shareable(),
- StyleStructRef::Borrowed(v) => v.clone(),
+ StyleStructRef::Borrowed(v) => clone_arc(v),
StyleStructRef::Vacated => panic!("Accessed vacated style struct")
}
}
}
impl<'a, T: 'a> Deref for StyleStructRef<'a, T> {
type Target = T;