Bug 1474793 - Part 10.8: Add derived ToShmem implementations. r=emilio
authorCameron McCormack <cam@mcc.id.au>
Sat, 30 Mar 2019 00:16:25 +0000
changeset 466906 7c9ebe38c5a98ed59d1df0d2b769d6e8d5fd4083
parent 466905 637160560b12e63b745bed56bae1c197a0326425
child 466907 e450b952d748478689a83dd2dd1914ad80fdc6fe
push id112603
push usernerli@mozilla.com
push dateSat, 30 Mar 2019 09:35:57 +0000
treeherdermozilla-inbound@7c3183c56eb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1474793
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1474793 - Part 10.8: Add derived ToShmem implementations. r=emilio Depends on D17196 Differential Revision: https://phabricator.services.mozilla.com/D17197
Cargo.lock
servo/components/selectors/Cargo.toml
servo/components/selectors/attr.rs
servo/components/selectors/builder.rs
servo/components/selectors/lib.rs
servo/components/selectors/parser.rs
servo/components/style/counter_style/mod.rs
servo/components/style/custom_properties.rs
servo/components/style/font_face.rs
servo/components/style/gecko/pseudo_element_definition.mako.rs
servo/components/style/gecko/selector_parser.rs
servo/components/style/gecko/url.rs
servo/components/style/gecko_string_cache/namespace.rs
servo/components/style/lib.rs
servo/components/style/macros.rs
servo/components/style/media_queries/media_condition.rs
servo/components/style/media_queries/media_feature_expression.rs
servo/components/style/media_queries/media_list.rs
servo/components/style/media_queries/media_query.rs
servo/components/style/properties/declaration_block.rs
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/longhands/font.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/selector_parser.rs
servo/components/style/stylesheets/document_rule.rs
servo/components/style/stylesheets/font_feature_values_rule.rs
servo/components/style/stylesheets/keyframes_rule.rs
servo/components/style/stylesheets/media_rule.rs
servo/components/style/stylesheets/mod.rs
servo/components/style/stylesheets/namespace_rule.rs
servo/components/style/stylesheets/origin.rs
servo/components/style/stylesheets/page_rule.rs
servo/components/style/stylesheets/rule_list.rs
servo/components/style/stylesheets/rule_parser.rs
servo/components/style/stylesheets/style_rule.rs
servo/components/style/stylesheets/supports_rule.rs
servo/components/style/stylesheets/viewport_rule.rs
servo/components/style/values/computed/font.rs
servo/components/style/values/computed/length.rs
servo/components/style/values/computed/percentage.rs
servo/components/style/values/generics/background.rs
servo/components/style/values/generics/basic_shape.rs
servo/components/style/values/generics/border.rs
servo/components/style/values/generics/box.rs
servo/components/style/values/generics/color.rs
servo/components/style/values/generics/column.rs
servo/components/style/values/generics/counters.rs
servo/components/style/values/generics/easing.rs
servo/components/style/values/generics/effects.rs
servo/components/style/values/generics/flex.rs
servo/components/style/values/generics/font.rs
servo/components/style/values/generics/gecko.rs
servo/components/style/values/generics/grid.rs
servo/components/style/values/generics/image.rs
servo/components/style/values/generics/length.rs
servo/components/style/values/generics/mod.rs
servo/components/style/values/generics/position.rs
servo/components/style/values/generics/rect.rs
servo/components/style/values/generics/size.rs
servo/components/style/values/generics/svg.rs
servo/components/style/values/generics/text.rs
servo/components/style/values/generics/transform.rs
servo/components/style/values/generics/ui.rs
servo/components/style/values/generics/url.rs
servo/components/style/values/mod.rs
servo/components/style/values/specified/align.rs
servo/components/style/values/specified/angle.rs
servo/components/style/values/specified/background.rs
servo/components/style/values/specified/border.rs
servo/components/style/values/specified/box.rs
servo/components/style/values/specified/calc.rs
servo/components/style/values/specified/color.rs
servo/components/style/values/specified/effects.rs
servo/components/style/values/specified/font.rs
servo/components/style/values/specified/image.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/list.rs
servo/components/style/values/specified/mod.rs
servo/components/style/values/specified/motion.rs
servo/components/style/values/specified/outline.rs
servo/components/style/values/specified/percentage.rs
servo/components/style/values/specified/position.rs
servo/components/style/values/specified/resolution.rs
servo/components/style/values/specified/svg.rs
servo/components/style/values/specified/svg_path.rs
servo/components/style/values/specified/table.rs
servo/components/style/values/specified/text.rs
servo/components/style/values/specified/time.rs
servo/components/style/values/specified/transform.rs
servo/components/style/values/specified/ui.rs
servo/components/style_traits/Cargo.toml
servo/components/style_traits/lib.rs
servo/components/style_traits/values.rs
servo/components/style_traits/viewport.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2486,16 +2486,18 @@ dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "to_shmem 0.0.1",
+ "to_shmem_derive 0.0.1",
 ]
 
 [[package]]
 name = "semver"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2763,16 +2765,18 @@ dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.21.0",
  "servo_arc 0.1.1",
+ "to_shmem 0.0.1",
+ "to_shmem_derive 0.0.1",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/components/selectors/Cargo.toml
+++ b/servo/components/selectors/Cargo.toml
@@ -26,11 +26,13 @@ cssparser = "0.25"
 derive_more = "0.13"
 log = "0.4"
 fxhash = "0.2"
 phf = "0.7.18"
 precomputed-hash = "0.1"
 servo_arc = { version = "0.1", path = "../servo_arc" }
 smallvec = "0.6"
 thin-slice = "0.1.0"
+to_shmem = { path = "../to_shmem" }
+to_shmem_derive = { path = "../to_shmem_derive" }
 
 [build-dependencies]
 phf_codegen = "0.7.18"
--- a/servo/components/selectors/attr.rs
+++ b/servo/components/selectors/attr.rs
@@ -1,43 +1,47 @@
 /* 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/. */
 
 use crate::parser::SelectorImpl;
 use cssparser::ToCss;
 use std::fmt;
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, ToShmem)]
+#[shmem(no_bounds)]
 pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
+    #[shmem(field_bound)]
     pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
+    #[shmem(field_bound)]
     pub local_name: Impl::LocalName,
     pub local_name_lower: Impl::LocalName,
+    #[shmem(field_bound)]
     pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
     pub never_matches: bool,
 }
 
 impl<Impl: SelectorImpl> AttrSelectorWithOptionalNamespace<Impl> {
     pub fn namespace(&self) -> Option<NamespaceConstraint<&Impl::NamespaceUrl>> {
         self.namespace.as_ref().map(|ns| match ns {
             NamespaceConstraint::Any => NamespaceConstraint::Any,
             NamespaceConstraint::Specific((_, ref url)) => NamespaceConstraint::Specific(url),
         })
     }
 }
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, ToShmem)]
 pub enum NamespaceConstraint<NamespaceUrl> {
     Any,
 
     /// Empty string for no namespace
     Specific(NamespaceUrl),
 }
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, ToShmem)]
 pub enum ParsedAttrSelectorOperation<AttrValue> {
     Exists,
     WithValue {
         operator: AttrSelectorOperator,
         case_sensitivity: ParsedCaseSensitivity,
         expected_value: AttrValue,
     },
 }
@@ -67,17 +71,17 @@ impl<AttrValue> AttrSelectorOperation<At
                 element_attr_value,
                 expected_value.as_ref(),
                 case_sensitivity,
             ),
         }
     }
 }
 
-#[derive(Clone, Copy, Eq, PartialEq)]
+#[derive(Clone, Copy, Eq, PartialEq, ToShmem)]
 pub enum AttrSelectorOperator {
     Equal,
     Includes,
     DashMatch,
     Prefix,
     Substring,
     Suffix,
 }
@@ -127,17 +131,17 @@ impl AttrSelectorOperator {
             },
         }
     }
 }
 
 /// The definition of whitespace per CSS Selectors Level 3 § 4.
 pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C'];
 
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
 pub enum ParsedCaseSensitivity {
     // 's' was specified.
     ExplicitCaseSensitive,
     // 'i' was specified.
     AsciiCaseInsensitive,
     // No flags were specified and HTML says this is a case-sensitive attribute.
     CaseSensitive,
     // No flags were specified and HTML says this is a case-insensitive attribute.
--- a/servo/components/selectors/builder.rs
+++ b/servo/components/selectors/builder.rs
@@ -194,17 +194,17 @@ fn split_from_end<T>(s: &[T], at: usize)
     s.split_at(s.len() - at)
 }
 
 pub const HAS_PSEUDO_BIT: u32 = 1 << 30;
 pub const HAS_SLOTTED_BIT: u32 = 1 << 31;
 
 /// We use ten bits for each specificity kind (id, class, element), and the two
 /// high bits for the pseudo and slotted flags.
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
 pub struct SpecificityAndFlags(pub u32);
 
 impl SpecificityAndFlags {
     #[inline]
     pub fn specificity(&self) -> u32 {
         self.0 & !(HAS_PSEUDO_BIT | HAS_SLOTTED_BIT)
     }
 
--- a/servo/components/selectors/lib.rs
+++ b/servo/components/selectors/lib.rs
@@ -16,16 +16,19 @@ extern crate fxhash;
 extern crate log;
 #[macro_use]
 extern crate matches;
 extern crate phf;
 extern crate precomputed_hash;
 extern crate servo_arc;
 extern crate smallvec;
 extern crate thin_slice;
+extern crate to_shmem;
+#[macro_use]
+extern crate to_shmem_derive;
 
 pub mod attr;
 pub mod bloom;
 mod builder;
 pub mod context;
 pub mod matching;
 mod nth_index_cache;
 pub mod parser;
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -216,18 +216,19 @@ pub trait Parser<'i> {
     fn namespace_for_prefix(
         &self,
         _prefix: &<Self::Impl as SelectorImpl>::NamespacePrefix,
     ) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
         None
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct SelectorList<Impl: SelectorImpl>(pub SmallVec<[Selector<Impl>; 1]>);
+#[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
+#[shmem(no_bounds)]
+pub struct SelectorList<Impl: SelectorImpl>(#[shmem(field_bound)] pub SmallVec<[Selector<Impl>; 1]>);
 
 impl<Impl: SelectorImpl> SelectorList<Impl> {
     /// Parse a comma-separated list of Selectors.
     /// <https://drafts.csswg.org/selectors/#grouping>
     ///
     /// Return the Selectors or Err if there is an invalid selector.
     pub fn parse<'i, 't, P>(
         parser: &P,
@@ -502,18 +503,19 @@ pub fn namespace_empty_string<Impl: Sele
 /// Additionally, we invert the order of top-level compound selectors so that
 /// each one matches left-to-right. This is because matching namespace, local name,
 /// id, and class are all relatively cheap, whereas matching pseudo-classes might
 /// be expensive (depending on the pseudo-class). Since authors tend to put the
 /// pseudo-classes on the right, it's faster to start matching on the left.
 ///
 /// This reordering doesn't change the semantics of selector matching, and we
 /// handle it in to_css to make it invisible to serialization.
-#[derive(Clone, Eq, PartialEq)]
-pub struct Selector<Impl: SelectorImpl>(ThinArc<SpecificityAndFlags, Component<Impl>>);
+#[derive(Clone, Eq, PartialEq, ToShmem)]
+#[shmem(no_bounds)]
+pub struct Selector<Impl: SelectorImpl>(#[shmem(field_bound)] ThinArc<SpecificityAndFlags, Component<Impl>>);
 
 impl<Impl: SelectorImpl> Selector<Impl> {
     #[inline]
     pub fn specificity(&self) -> u32 {
         self.0.header.header.specificity()
     }
 
     #[inline]
@@ -771,17 +773,17 @@ impl<'a, Impl: SelectorImpl> Iterator fo
                 self.skip_until_ancestor();
             }
         }
 
         self.0.next()
     }
 }
 
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
 pub enum Combinator {
     Child,        //  >
     Descendant,   // space
     NextSibling,  // +
     LaterSibling, // ~
     /// A dummy combinator we use to the left of pseudo-elements.
     ///
     /// It serializes as the empty string, and acts effectively as a child
@@ -819,39 +821,42 @@ impl Combinator {
         matches!(*self, Combinator::NextSibling | Combinator::LaterSibling)
     }
 }
 
 /// A CSS simple selector or combinator. We store both in the same enum for
 /// optimal packing and cache performance, see [1].
 ///
 /// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1357973
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, ToShmem)]
+#[shmem(no_bounds)]
 pub enum Component<Impl: SelectorImpl> {
     Combinator(Combinator),
 
     ExplicitAnyNamespace,
     ExplicitNoNamespace,
-    DefaultNamespace(Impl::NamespaceUrl),
-    Namespace(Impl::NamespacePrefix, Impl::NamespaceUrl),
+    DefaultNamespace(#[shmem(field_bound)] Impl::NamespaceUrl),
+    Namespace(#[shmem(field_bound)] Impl::NamespacePrefix, #[shmem(field_bound)] Impl::NamespaceUrl),
 
     ExplicitUniversalType,
     LocalName(LocalName<Impl>),
 
-    ID(Impl::Identifier),
-    Class(Impl::ClassName),
+    ID(#[shmem(field_bound)] Impl::Identifier),
+    Class(#[shmem(field_bound)] Impl::ClassName),
 
     AttributeInNoNamespaceExists {
+        #[shmem(field_bound)]
         local_name: Impl::LocalName,
         local_name_lower: Impl::LocalName,
     },
     // Used only when local_name is already lowercase.
     AttributeInNoNamespace {
         local_name: Impl::LocalName,
         operator: AttrSelectorOperator,
+        #[shmem(field_bound)]
         value: Impl::AttrValue,
         case_sensitivity: ParsedCaseSensitivity,
         never_matches: bool,
     },
     // Use a Box in the less common cases with more data to keep size_of::<Component>() small.
     AttributeOther(Box<AttrSelectorWithOptionalNamespace<Impl>>),
 
     /// Pseudo-classes
@@ -873,17 +878,17 @@ pub enum Component<Impl: SelectorImpl> {
     Scope,
     NthChild(i32, i32),
     NthLastChild(i32, i32),
     NthOfType(i32, i32),
     NthLastOfType(i32, i32),
     FirstOfType,
     LastOfType,
     OnlyOfType,
-    NonTSPseudoClass(Impl::NonTSPseudoClass),
+    NonTSPseudoClass(#[shmem(field_bound)] Impl::NonTSPseudoClass),
     /// The ::slotted() pseudo-element (which isn't actually a pseudo-element,
     /// and probably should be a pseudo-class):
     ///
     /// https://drafts.csswg.org/css-scoping/#slotted-pseudo
     ///
     /// The selector here is a compound selector, that is, no combinators.
     ///
     /// NOTE(emilio): This should support a list of selectors, but as of this
@@ -897,17 +902,17 @@ pub enum Component<Impl: SelectorImpl> {
     /// https://drafts.csswg.org/css-scoping/#host-selector
     ///
     /// NOTE(emilio): This should support a list of selectors, but as of this
     /// writing no other browser does, and that allows them to put :host()
     /// in the rule hash, so we do that too.
     ///
     /// See https://github.com/w3c/csswg-drafts/issues/2158
     Host(Option<Selector<Impl>>),
-    PseudoElement(Impl::PseudoElement),
+    PseudoElement(#[shmem(field_bound)] Impl::PseudoElement),
 }
 
 impl<Impl: SelectorImpl> Component<Impl> {
     /// Compute the ancestor hash to check against the bloom filter.
     fn ancestor_hash(&self, quirks_mode: QuirksMode) -> Option<u32>
     where
         Impl::Identifier: PrecomputedHash,
         Impl::ClassName: PrecomputedHash,
@@ -952,18 +957,20 @@ impl<Impl: SelectorImpl> Component<Impl>
     pub fn as_combinator(&self) -> Option<Combinator> {
         match *self {
             Component::Combinator(c) => Some(c),
             _ => None,
         }
     }
 }
 
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq, ToShmem)]
+#[shmem(no_bounds)]
 pub struct LocalName<Impl: SelectorImpl> {
+    #[shmem(field_bound)]
     pub name: Impl::LocalName,
     pub lower_name: Impl::LocalName,
 }
 
 impl<Impl: SelectorImpl> Debug for Selector<Impl> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str("Selector(")?;
         self.to_css(f)?;
--- a/servo/components/style/counter_style/mod.rs
+++ b/servo/components/style/counter_style/mod.rs
@@ -159,17 +159,17 @@ macro_rules! checker {
     };
 }
 
 macro_rules! counter_style_descriptors {
     (
         $( #[$doc: meta] $name: tt $ident: ident / $setter: ident [$checker: tt]: $ty: ty, )+
     ) => {
         /// An @counter-style rule
-        #[derive(Clone, Debug)]
+        #[derive(Clone, Debug, ToShmem)]
         pub struct CounterStyleRuleData {
             name: CustomIdent,
             generation: Wrapping<u32>,
             $(
                 #[$doc]
                 $ident: Option<$ty>,
             )+
             /// Line and column of the @counter-style rule source code.
@@ -332,17 +332,17 @@ impl CounterStyleRuleData {
         match self.system {
             Some(ref system) => system,
             None => &System::Symbolic,
         }
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#counter-style-system>
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, ToShmem)]
 pub enum System {
     /// 'cyclic'
     Cyclic,
     /// 'numeric'
     Numeric,
     /// 'alphabetic'
     Alphabetic,
     /// 'symbolic'
@@ -405,17 +405,17 @@ impl ToCss for System {
                 other.to_css(dest)
             },
         }
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol>
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub enum Symbol {
     /// <string>
     String(String),
     /// <custom-ident>
     Ident(CustomIdent),
     // Not implemented:
     // /// <image>
     // Image(Image),
@@ -442,17 +442,17 @@ impl Symbol {
             // Identifier is not allowed.
             &Symbol::Ident(_) => false,
             _ => true,
         }
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#counter-style-negative>
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub struct Negative(pub Symbol, pub Option<Symbol>);
 
 impl Parse for Negative {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         Ok(Negative(
@@ -460,21 +460,21 @@ impl Parse for Negative {
             input.try(|input| Symbol::parse(context, input)).ok(),
         ))
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#counter-style-range>
 ///
 /// Empty Vec represents 'auto'
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, ToShmem)]
 pub struct Ranges(pub Vec<Range<CounterBound>>);
 
 /// A bound found in `Ranges`.
-#[derive(Clone, Copy, Debug, ToCss)]
+#[derive(Clone, Copy, Debug, ToCss, ToShmem)]
 pub enum CounterBound {
     /// An integer bound.
     Integer(Integer),
     /// The infinite bound.
     Infinite,
 }
 
 impl Parse for Ranges {
@@ -543,47 +543,47 @@ where
     W: Write,
 {
     range.start.to_css(dest)?;
     dest.write_char(' ')?;
     range.end.to_css(dest)
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#counter-style-pad>
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub struct Pad(pub Integer, pub Symbol);
 
 impl Parse for Pad {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         let pad_with = input.try(|input| Symbol::parse(context, input));
         let min_length = Integer::parse_non_negative(context, input)?;
         let pad_with = pad_with.or_else(|_| Symbol::parse(context, input))?;
         Ok(Pad(min_length, pad_with))
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#counter-style-fallback>
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub struct Fallback(pub CustomIdent);
 
 impl Parse for Fallback {
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         parse_counter_style_name(input).map(Fallback)
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols>
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct Symbols(#[css(iterable)] pub Vec<Symbol>);
 
 impl Parse for Symbols {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         let mut symbols = Vec::new();
@@ -597,17 +597,17 @@ impl Parse for Symbols {
                     return Ok(Symbols(symbols));
                 }
             }
         }
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-additive-symbols>
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);
 
 impl Parse for AdditiveSymbols {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         let tuples = Vec::<AdditiveTuple>::parse(context, input)?;
@@ -618,17 +618,17 @@ impl Parse for AdditiveSymbols {
         {
             return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
         }
         Ok(AdditiveSymbols(tuples))
     }
 }
 
 /// <integer> && <symbol>
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub struct AdditiveTuple {
     /// <integer>
     pub weight: Integer,
     /// <symbol>
     pub symbol: Symbol,
 }
 
 impl OneOrMoreSeparated for AdditiveTuple {
@@ -646,17 +646,17 @@ impl Parse for AdditiveTuple {
         Ok(AdditiveTuple {
             weight: weight,
             symbol: symbol,
         })
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#counter-style-speak-as>
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub enum SpeakAs {
     /// auto
     Auto,
     /// bullets
     Bullets,
     /// numbers
     Numbers,
     /// words
--- a/servo/components/style/custom_properties.rs
+++ b/servo/components/style/custom_properties.rs
@@ -91,17 +91,17 @@ pub fn parse_name(s: &str) -> Result<&st
         Err(())
     }
 }
 
 /// A value for a custom property is just a set of tokens.
 ///
 /// We preserve the original CSS for serialization, and also the variable
 /// references to other custom property names.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub struct VariableValue {
     css: String,
 
     first_token_type: TokenSerializationType,
     last_token_type: TokenSerializationType,
 
     /// Whether a variable value has a reference to an environment variable.
     ///
--- a/servo/components/style/font_face.rs
+++ b/servo/components/style/font_face.rs
@@ -29,17 +29,17 @@ use cssparser::{CowRcStr, SourceLocation
 use selectors::parser::SelectorParseErrorKind;
 use std::fmt::{self, Write};
 use style_traits::values::SequenceWriter;
 use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError};
 use style_traits::{StyleParseErrorKind, ToCss};
 
 /// A source for a font-face rule.
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
+#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
 pub enum Source {
     /// A `url()` source.
     Url(UrlSource),
     /// A `local()` source.
     #[css(function)]
     Local(FamilyName),
 }
 
@@ -63,17 +63,17 @@ pub enum FontFaceSourceListComponent {
     },
 }
 
 /// A `UrlSource` represents a font-face source that has been specified with a
 /// `url()` function.
 ///
 /// <https://drafts.csswg.org/css-fonts/#src-desc>
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
 pub struct UrlSource {
     /// The specified url.
     pub url: SpecifiedUrl,
     /// The format hints specified with the `format()` function.
     pub format_hints: Vec<String>,
 }
 
 impl ToCss for UrlSource {
@@ -96,17 +96,19 @@ impl ToCss for UrlSource {
     }
 }
 
 /// A font-display value for a @font-face rule.
 /// The font-display descriptor determines how a font face is displayed based
 /// on whether and when it is downloaded and ready to use.
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss, ToShmem,
+)]
 #[repr(u8)]
 pub enum FontDisplay {
     Auto,
     Block,
     Swap,
     Fallback,
     Optional,
 }
@@ -139,17 +141,17 @@ macro_rules! impl_range {
             }
         }
     };
 }
 
 /// The font-weight descriptor:
 ///
 /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-weight
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, ToShmem)]
 pub struct FontWeightRange(pub AbsoluteFontWeight, pub AbsoluteFontWeight);
 impl_range!(FontWeightRange, AbsoluteFontWeight);
 
 /// The computed representation of the above so Gecko can read them easily.
 ///
 /// This one is needed because cbindgen doesn't know how to generate
 /// specified::Number.
 #[repr(C)]
@@ -171,17 +173,17 @@ impl FontWeightRange {
         let (min, max) = sort_range(self.0.compute().0, self.1.compute().0);
         ComputedFontWeightRange(min, max)
     }
 }
 
 /// The font-stretch descriptor:
 ///
 /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-stretch
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, ToShmem)]
 pub struct FontStretchRange(pub FontStretch, pub FontStretch);
 impl_range!(FontStretchRange, FontStretch);
 
 /// The computed representation of the above, so that
 /// Gecko can read them easily.
 #[repr(C)]
 #[allow(missing_docs)]
 pub struct ComputedFontStretchRange(f32, f32);
@@ -200,17 +202,17 @@ impl FontStretchRange {
         let (min, max) = sort_range(compute_stretch(&self.0), compute_stretch(&self.1));
         ComputedFontStretchRange(min, max)
     }
 }
 
 /// The font-style descriptor:
 ///
 /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-style
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, ToShmem)]
 #[allow(missing_docs)]
 pub enum FontStyle {
     Normal,
     Italic,
     Oblique(Angle, Angle),
 }
 
 /// The computed representation of the above, with angles in degrees, so that
@@ -430,17 +432,17 @@ macro_rules! is_descriptor_enabled {
 
 macro_rules! font_face_descriptors_common {
     (
         $( #[$doc: meta] $name: tt $ident: ident / $gecko_ident: ident: $ty: ty, )*
     ) => {
         /// Data inside a `@font-face` rule.
         ///
         /// <https://drafts.csswg.org/css-fonts/#font-face-rule>
-        #[derive(Clone, Debug, PartialEq)]
+        #[derive(Clone, Debug, PartialEq, ToShmem)]
         pub struct FontFaceRuleData {
             $(
                 #[$doc]
                 pub $ident: Option<$ty>,
             )*
             /// Line and column of the @font-face rule source code.
             pub source_location: SourceLocation,
         }
--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs
@@ -1,14 +1,14 @@
 /* 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/. */
 
 /// Gecko's pseudo-element definition.
-#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 pub enum PseudoElement {
     % for pseudo in PSEUDOS:
         /// ${pseudo.value}
         % if pseudo.is_tree_pseudo_element():
         ${pseudo.capitalized_pseudo()}(ThinBoxedSlice<Atom>),
         % else:
         ${pseudo.capitalized_pseudo()},
         % endif
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -39,17 +39,17 @@ bitflags! {
 }
 
 /// The type used to store the language argument to the `:lang` pseudo-class.
 pub type Lang = Atom;
 
 macro_rules! pseudo_class_name {
     ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
         /// Our representation of a non tree-structural pseudo-class.
-        #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
+        #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
         pub enum NonTSPseudoClass {
             $(
                 #[doc = $css]
                 $name,
             )*
             /// The `:lang` pseudo-class.
             Lang(Lang),
             /// The `:dir` pseudo-class.
--- a/servo/components/style/gecko/url.rs
+++ b/servo/components/style/gecko/url.rs
@@ -21,21 +21,21 @@ use std::collections::HashMap;
 use std::fmt::{self, Write};
 use std::mem::ManuallyDrop;
 use std::sync::RwLock;
 use style_traits::{CssWriter, ParseError, ToCss};
 use to_shmem::{SharedMemoryBuilder, ToShmem};
 
 /// A CSS url() value for gecko.
 #[css(function = "url")]
-#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub struct CssUrl(pub Arc<CssUrlData>);
 
 /// Data shared between CssUrls.
-#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub struct CssUrlData {
     /// The URL in unresolved string form.
     serialization: String,
 
     /// The URL extra data.
     #[css(skip)]
     pub extra_data: UrlExtraData,
 }
@@ -145,17 +145,17 @@ impl ToShmem for URLValueSource {
         ManuallyDrop::new(match self {
             URLValueSource::URLValue(r) => URLValueSource::CORSMode(r.mCORSMode),
             URLValueSource::CORSMode(c) => URLValueSource::CORSMode(*c),
         })
     }
 }
 
 /// A specified non-image `url()` value.
-#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, SpecifiedValueInfo, ToCss, ToShmem)]
 pub struct SpecifiedUrl {
     /// The specified url value.
     pub url: CssUrl,
     /// Gecko's URLValue so that we can reuse it while rematching a
     /// property with this specified value.
     ///
     /// Box this to avoid SpecifiedUrl getting bigger than two words,
     /// and increasing the size of PropertyDeclaration.
@@ -271,17 +271,17 @@ impl ToComputedValue for SpecifiedUrl {
 
     #[inline]
     fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         computed.0.clone()
     }
 }
 
 /// A specified image `url()` value.
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub struct SpecifiedImageUrl(pub SpecifiedUrl);
 
 impl SpecifiedImageUrl {
     /// Parse a URL from a string value that is a valid CSS token for a URL.
     pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
         SpecifiedImageUrl(SpecifiedUrl::parse_from_string(url, context))
     }
 
--- a/servo/components/style/gecko_string_cache/namespace.rs
+++ b/servo/components/style/gecko_string_cache/namespace.rs
@@ -19,17 +19,17 @@ macro_rules! ns {
         $crate::string_cache::Namespace(atom!(""))
     };
     ($s:tt) => {
         $crate::string_cache::Namespace(atom!($s))
     };
 }
 
 /// A Gecko namespace is just a wrapped atom.
-#[derive(Clone, Debug, Default, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, Default, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 pub struct Namespace(pub Atom);
 
 impl PrecomputedHash for Namespace {
     #[inline]
     fn precomputed_hash(&self) -> u32 {
         self.0.precomputed_hash()
     }
 }
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -95,16 +95,17 @@ extern crate smallvec;
 extern crate string_cache;
 #[macro_use]
 extern crate style_derive;
 extern crate style_traits;
 #[cfg(feature = "gecko")]
 extern crate thin_slice;
 extern crate time;
 extern crate to_shmem;
+#[macro_use]
 extern crate to_shmem_derive;
 extern crate uluru;
 extern crate unicode_bidi;
 #[allow(unused_extern_crates)]
 extern crate unicode_segmentation;
 extern crate void;
 
 #[macro_use]
--- a/servo/components/style/macros.rs
+++ b/servo/components/style/macros.rs
@@ -75,16 +75,17 @@ macro_rules! define_keyword_type {
             Copy,
             MallocSizeOf,
             PartialEq,
             SpecifiedValueInfo,
             ToAnimatedValue,
             ToAnimatedZero,
             ToComputedValue,
             ToCss,
+            ToShmem,
         )]
         pub struct $name;
 
         impl fmt::Debug for $name {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 f.write_str($css)
             }
         }
--- a/servo/components/style/media_queries/media_condition.rs
+++ b/servo/components/style/media_queries/media_condition.rs
@@ -9,32 +9,32 @@
 use super::{Device, MediaFeatureExpression};
 use crate::context::QuirksMode;
 use crate::parser::ParserContext;
 use cssparser::{Parser, Token};
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
 /// A binary `and` or `or` operator.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)]
 #[allow(missing_docs)]
 pub enum Operator {
     And,
     Or,
 }
 
 /// Whether to allow an `or` condition or not during parsing.
 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
 enum AllowOr {
     Yes,
     No,
 }
 
 /// Represents a media condition.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub enum MediaCondition {
     /// A simple media feature expression, implicitly parenthesized.
     Feature(MediaFeatureExpression),
     /// A negation of a condition.
     Not(Box<MediaCondition>),
     /// A set of joint operations.
     Operation(Box<[MediaCondition]>, Operator),
     /// A condition wrapped in parenthesis.
--- a/servo/components/style/media_queries/media_feature_expression.rs
+++ b/servo/components/style/media_queries/media_feature_expression.rs
@@ -22,17 +22,17 @@ use crate::values::specified::{Integer, 
 use crate::values::{serialize_atom_identifier, CSSFloat};
 use crate::{Atom, Zero};
 use cssparser::{Parser, Token};
 use std::cmp::{Ordering, PartialOrd};
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
 /// An aspect ratio, with a numerator and denominator.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub struct AspectRatio(pub u32, pub u32);
 
 impl ToCss for AspectRatio {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: fmt::Write,
     {
         self.0.to_css(dest)?;
@@ -46,26 +46,26 @@ impl PartialOrd for AspectRatio {
         u64::partial_cmp(
             &(self.0 as u64 * other.1 as u64),
             &(self.1 as u64 * other.0 as u64),
         )
     }
 }
 
 /// The kind of matching that should be performed on a media feature value.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub enum Range {
     /// At least the specified value.
     Min,
     /// At most the specified value.
     Max,
 }
 
 /// The operator that was specified in this media feature.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub enum Operator {
     /// =
     Equal,
     /// >
     GreaterThan,
     /// >=
     GreaterThanEqual,
     /// <
@@ -88,17 +88,17 @@ impl ToCss for Operator {
         })
     }
 }
 
 /// Either a `Range` or an `Operator`.
 ///
 /// Ranged media features are not allowed with operations (that'd make no
 /// sense).
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub enum RangeOrOperator {
     /// A `Range`.
     Range(Range),
     /// An `Operator`.
     Operator(Operator),
 }
 
 impl RangeOrOperator {
@@ -146,17 +146,17 @@ impl RangeOrOperator {
                 Operator::LessThanEqual => cmp == Ordering::Equal || cmp == Ordering::Less,
             },
         }
     }
 }
 
 /// A feature expression contains a reference to the media feature, the value
 /// the media query contained, and the range to evaluate.
-#[derive(Clone, Debug, MallocSizeOf)]
+#[derive(Clone, Debug, MallocSizeOf, ToShmem)]
 pub struct MediaFeatureExpression {
     feature_index: usize,
     value: Option<MediaExpressionValue>,
     range_or_operator: Option<RangeOrOperator>,
 }
 
 impl PartialEq for MediaFeatureExpression {
     fn eq(&self, other: &Self) -> bool {
@@ -462,17 +462,17 @@ impl MediaFeatureExpression {
 /// A value found or expected in a media expression.
 ///
 /// FIXME(emilio): How should calc() serialize in the Number / Integer /
 /// BoolInteger / IntRatio case, as computed or as specified value?
 ///
 /// If the first, this would need to store the relevant values.
 ///
 /// See: https://github.com/w3c/csswg-drafts/issues/1968
-#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub enum MediaExpressionValue {
     /// A length.
     Length(Length),
     /// A (non-negative) integer.
     Integer(u32),
     /// A floating point value.
     Float(CSSFloat),
     /// A boolean value, specified as an integer (i.e., either 0 or 1).
--- a/servo/components/style/media_queries/media_list.rs
+++ b/servo/components/style/media_queries/media_list.rs
@@ -10,17 +10,17 @@ use super::{Device, MediaQuery, Qualifie
 use crate::context::QuirksMode;
 use crate::error_reporting::ContextualParseError;
 use crate::parser::ParserContext;
 use cssparser::{Delimiter, Parser};
 use cssparser::{ParserInput, Token};
 
 /// A type that encapsulates a media query list.
 #[css(comma, derive_debug)]
-#[derive(Clone, MallocSizeOf, ToCss)]
+#[derive(Clone, MallocSizeOf, ToCss, ToShmem)]
 pub struct MediaList {
     /// The list of media queries.
     #[css(iterable)]
     pub media_queries: Vec<MediaQuery>,
 }
 
 impl MediaList {
     /// Parse a media query list from CSS.
--- a/servo/components/style/media_queries/media_query.rs
+++ b/servo/components/style/media_queries/media_query.rs
@@ -11,28 +11,28 @@ use crate::parser::ParserContext;
 use crate::str::string_as_ascii_lowercase;
 use crate::values::CustomIdent;
 use crate::Atom;
 use cssparser::Parser;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, ToCss};
 
 /// <https://drafts.csswg.org/mediaqueries/#mq-prefix>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)]
 pub enum Qualifier {
     /// Hide a media query from legacy UAs:
     /// <https://drafts.csswg.org/mediaqueries/#mq-only>
     Only,
     /// Negate a media query:
     /// <https://drafts.csswg.org/mediaqueries/#mq-not>
     Not,
 }
 
 /// <https://drafts.csswg.org/mediaqueries/#media-types>
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub struct MediaType(pub CustomIdent);
 
 impl MediaType {
     /// The `screen` media type.
     pub fn screen() -> Self {
         MediaType(CustomIdent(atom!("screen")))
     }
 
@@ -53,17 +53,17 @@ impl MediaType {
             _ => Ok(MediaType(CustomIdent(Atom::from(string_as_ascii_lowercase(name))))),
         }
     }
 }
 
 /// A [media query][mq].
 ///
 /// [mq]: https://drafts.csswg.org/mediaqueries/
-#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub struct MediaQuery {
     /// The qualifier for this query.
     pub qualifier: Option<Qualifier>,
     /// The media type for this query, that can be known, unknown, or "all".
     pub media_type: MediaQueryType,
     /// The condition that this media query contains. This cannot have `or`
     /// in the first level.
     pub condition: Option<MediaCondition>,
@@ -146,17 +146,17 @@ impl MediaQuery {
             qualifier,
             media_type,
             condition,
         })
     }
 }
 
 /// <http://dev.w3.org/csswg/mediaqueries-3/#media0>
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub enum MediaQueryType {
     /// A media type that matches every device.
     All,
     /// A specific media type.
     Concrete(MediaType),
 }
 
 impl MediaQueryType {
--- a/servo/components/style/properties/declaration_block.rs
+++ b/servo/components/style/properties/declaration_block.rs
@@ -85,17 +85,17 @@ impl Importance {
             Importance::Normal => false,
             Importance::Important => true,
         }
     }
 }
 
 /// Overridden declarations are skipped.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone)]
+#[derive(Clone, ToShmem)]
 pub struct PropertyDeclarationBlock {
     /// The group of declarations, along with their importance.
     ///
     /// Only deduplicated declarations appear here.
     declarations: Vec<PropertyDeclaration>,
 
     /// The "important" flag for each declaration in `declarations`.
     declarations_importance: SmallBitVec,
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -200,17 +200,17 @@
                 }
             }
         }
 
         /// The specified value of ${name}.
         % if separator == "Comma":
         #[css(comma)]
         % endif
-        #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+        #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
         pub struct SpecifiedValue(
             % if not allow_empty:
             #[css(iterable)]
             % else:
             #[css(if_empty = "none", iterable)]
             % endif
             pub Vec<single_value::SpecifiedValue>,
         );
@@ -421,28 +421,28 @@
         keyword = keyword=Keyword(name, values, **keyword_kwargs)
     %>
     <%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
         use crate::properties::longhands::system_font::SystemFont;
 
         pub mod computed_value {
             #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
             #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse,
-                     PartialEq, SpecifiedValueInfo, ToCss)]
+                     PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
             pub enum T {
             % for value in keyword.values_for(product):
                 ${to_camel_case(value)},
             % endfor
             }
 
             ${gecko_keyword_conversion(keyword, keyword.values_for(product), type="T", cast_to="i32")}
         }
 
         #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-        #[derive(Clone, Copy, Debug, Eq, PartialEq, SpecifiedValueInfo, ToCss)]
+        #[derive(Clone, Copy, Debug, Eq, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
         pub enum SpecifiedValue {
             Keyword(computed_value::T),
             #[css(skip)]
             System(SystemFont),
         }
 
         pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> {
             Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
@@ -584,28 +584,28 @@
             % endif
             % endif
             ${to_camel_case(variant)},
             % endfor
         </%def>
         % if extra_specified:
             #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
             #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq,
-                     SpecifiedValueInfo, ToCss)]
+                     SpecifiedValueInfo, ToCss, ToShmem)]
             pub enum SpecifiedValue {
                 ${variants(keyword.values_for(product) + extra_specified.split(), bool(extra_specified))}
             }
         % else:
             pub use self::computed_value::T as SpecifiedValue;
         % endif
         pub mod computed_value {
             #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
             #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
             % if not extra_specified:
-            #[derive(Parse, SpecifiedValueInfo, ToComputedValue)]
+            #[derive(Parse, SpecifiedValueInfo, ToComputedValue, ToShmem)]
             % endif
             pub enum T {
                 ${variants(data.longhands_by_name[name].keyword.values_for(product), not extra_specified)}
             }
         }
         #[inline]
         pub fn get_initial_value() -> computed_value::T {
             computed_value::T::${to_camel_case(values.split()[0])}
--- a/servo/components/style/properties/longhands/font.mako.rs
+++ b/servo/components/style/properties/longhands/font.mako.rs
@@ -341,17 +341,17 @@ https://drafts.csswg.org/css-fonts-4/#lo
             kw_font_props = """font_variant_caps
                                font_kerning font_variant_position font_variant_ligatures
                                font_variant_east_asian font_variant_numeric
                                font_optical_sizing""".split()
             kw_cast = """font_variant_caps font_kerning font_variant_position
                          font_optical_sizing""".split()
         %>
         #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq,
-                 SpecifiedValueInfo, ToCss)]
+                 SpecifiedValueInfo, ToCss, ToShmem)]
         pub enum SystemFont {
             % for font in system_fonts:
                 ${to_camel_case(font)},
             % endfor
         }
 
         // ComputedValues are compared at times
         // so we need these impls. We don't want to
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -252,16 +252,17 @@ pub mod shorthands {
         },
     ]
     for v in extra:
         variants.append(v)
         groups[v["type"]] = [v]
 %>
 
 /// Servo's representation for a property declaration.
+#[derive(ToShmem)]
 #[repr(u16)]
 pub enum PropertyDeclaration {
     % for variant in variants:
     /// ${variant["doc"]}
     ${variant["name"]}(${variant["type"]}),
     % endfor
 }
 
@@ -891,17 +892,17 @@ impl LonghandIdSet {
     #[inline]
     pub fn is_empty(&self) -> bool {
         self.storage.iter().all(|c| *c == 0)
     }
 }
 
 /// An enum to represent a CSS Wide keyword.
 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToCss)]
+         ToCss, ToShmem)]
 pub enum CSSWideKeyword {
     /// The `initial` keyword.
     Initial,
     /// The `inherit` keyword.
     Inherit,
     /// The `unset` keyword.
     Unset,
     /// The `revert` keyword.
@@ -991,17 +992,17 @@ bitflags! {
 pub enum LogicalGroup {
     % for group in logical_groups.iterkeys():
     /// ${group}
     ${to_camel_case(group)},
     % endfor
 }
 
 /// An identifier for a given longhand property.
-#[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[repr(u16)]
 pub enum LonghandId {
     % for i, property in enumerate(data.longhands):
         /// ${property.name}
         ${property.camel_case} = ${i},
     % endfor
 }
 
@@ -1333,17 +1334,17 @@ where
             if !self.filter || id.into().enabled_for_all_content() {
                 return Some(id)
             }
         }
     }
 }
 
 /// An identifier for a given shorthand property.
-#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[repr(u16)]
 pub enum ShorthandId {
     % for i, property in enumerate(data.shorthands):
         /// ${property.name}
         ${property.camel_case} = ${i},
     % endfor
 }
 
@@ -1531,17 +1532,17 @@ impl ShorthandId {
             % endfor
             // 'all' accepts no value other than CSS-wide keywords
             ShorthandId::All => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
         }
     }
 }
 
 /// An unparsed property value that contains `var()` functions.
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Debug, Eq, PartialEq, ToShmem)]
 pub struct UnparsedValue {
     /// The css serialization for this value.
     css: String,
     /// The first token type for this serialization.
     first_token_type: TokenSerializationType,
     /// The url data for resolving url values.
     url_data: UrlExtraData,
     /// The shorthand this came from.
@@ -1952,46 +1953,46 @@ impl PropertyId {
             id.collect_property_completion_keywords(f);
         }
         CSSWideKeyword::collect_completion_keywords(f);
     }
 }
 
 /// A declaration using a CSS-wide keyword.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, PartialEq, ToCss)]
+#[derive(Clone, PartialEq, ToCss, ToShmem)]
 pub struct WideKeywordDeclaration {
     #[css(skip)]
     id: LonghandId,
     keyword: CSSWideKeyword,
 }
 
 /// An unparsed declaration that contains `var()` functions.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, PartialEq, ToCss)]
+#[derive(Clone, PartialEq, ToCss, ToShmem)]
 pub struct VariableDeclaration {
     #[css(skip)]
     id: LonghandId,
     #[cfg_attr(feature = "gecko", ignore_malloc_size_of = "XXX: how to handle this?")]
     value: Arc<UnparsedValue>,
 }
 
 /// A custom property declaration value is either an unparsed value or a CSS
 /// wide-keyword.
-#[derive(Clone, PartialEq, ToCss)]
+#[derive(Clone, PartialEq, ToCss, ToShmem)]
 pub enum CustomDeclarationValue {
     /// A value.
     Value(Arc<crate::custom_properties::SpecifiedValue>),
     /// A wide keyword.
     CSSWideKeyword(CSSWideKeyword),
 }
 
 /// A custom property declaration with the property name and the declared value.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, PartialEq, ToCss)]
+#[derive(Clone, PartialEq, ToCss, ToShmem)]
 pub struct CustomDeclaration {
     /// The name of the custom property.
     #[css(skip)]
     pub name: crate::custom_properties::Name,
     /// The value of the custom property.
     #[cfg_attr(feature = "gecko", ignore_malloc_size_of = "XXX: how to handle this?")]
     pub value: CustomDeclarationValue,
 }
--- a/servo/components/style/selector_parser.rs
+++ b/servo/components/style/selector_parser.rs
@@ -172,17 +172,17 @@ impl<T> PerPseudoElementMap<T> {
     pub fn iter(&self) -> ::std::slice::Iter<Option<T>> {
         self.entries.iter()
     }
 }
 
 /// Values for the :dir() pseudo class
 ///
 /// "ltr" and "rtl" values are normalized to lowercase.
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub struct Direction(pub Atom);
 
 /// Horizontal values for the :dir() pseudo class
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub enum HorizontalDirection {
     /// :dir(ltr)
     Ltr,
     /// :dir(rtl)
--- a/servo/components/style/stylesheets/document_rule.rs
+++ b/servo/components/style/stylesheets/document_rule.rs
@@ -15,17 +15,17 @@ use crate::stylesheets::CssRules;
 use crate::values::CssUrl;
 use cssparser::{Parser, SourceLocation};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
 use servo_arc::Arc;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 /// A @-moz-document rule
 pub struct DocumentRule {
     /// The parsed condition
     pub condition: DocumentCondition,
     /// Child rules
     pub rules: Arc<Locked<CssRules>>,
     /// The line and column of the rule's source code.
     pub source_location: SourceLocation,
@@ -67,27 +67,27 @@ impl DeepCloneWithLock for DocumentRule 
             condition: self.condition.clone(),
             rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))),
             source_location: self.source_location.clone(),
         }
     }
 }
 
 /// The kind of media document that the rule will match.
-#[derive(Clone, Copy, Debug, Parse, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, Parse, PartialEq, ToCss, ToShmem)]
 #[allow(missing_docs)]
 pub enum MediaDocumentKind {
     All,
     Plugin,
     Image,
     Video,
 }
 
 /// A matching function for a `@document` rule's condition.
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub enum DocumentMatchingFunction {
     /// Exact URL matching function. It evaluates to true whenever the
     /// URL of the document being styled is exactly the URL given.
     Url(CssUrl),
     /// URL prefix matching function. It evaluates to true whenever the
     /// URL of the document being styled has the argument to the
     /// function as an initial substring (which is true when the two
     /// strings are equal). When the argument is the empty string,
@@ -211,17 +211,17 @@ impl DocumentMatchingFunction {
 /// A `@document` rule's condition.
 ///
 /// <https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#at-document>
 ///
 /// The `@document` rule's condition is written as a comma-separated list of
 /// URL matching functions, and the condition evaluates to true whenever any
 /// one of those functions evaluates to true.
 #[css(comma)]
-#[derive(Clone, Debug, ToCss)]
+#[derive(Clone, Debug, ToCss, ToShmem)]
 pub struct DocumentCondition(#[css(iterable)] Vec<DocumentMatchingFunction>);
 
 impl DocumentCondition {
     /// Parse a document condition.
     pub fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
--- a/servo/components/style/stylesheets/font_feature_values_rule.rs
+++ b/servo/components/style/stylesheets/font_feature_values_rule.rs
@@ -25,17 +25,17 @@ use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
 /// A @font-feature-values block declaration.
 /// It is `<ident>: <integer>+`.
 /// This struct can take 3 value types.
 /// - `SingleValue` is to keep just one unsigned integer value.
 /// - `PairValues` is to keep one or two unsigned integer values.
 /// - `VectorValues` is to keep a list of unsigned integer values.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, ToShmem)]
 pub struct FFVDeclaration<T> {
     /// An `<ident>` for declaration name.
     pub name: Atom,
     /// An `<integer>+` for declaration value.
     pub value: T,
 }
 
 impl<T: ToCss> ToCss for FFVDeclaration<T> {
@@ -53,17 +53,17 @@ impl<T: ToCss> ToCss for FFVDeclaration<
 /// A trait for @font-feature-values rule to gecko values conversion.
 #[cfg(feature = "gecko")]
 pub trait ToGeckoFontFeatureValues {
     /// Sets the equivalent of declaration to gecko `nsTArray<u32>` array.
     fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>);
 }
 
 /// A @font-feature-values block declaration value that keeps one value.
-#[derive(Clone, Debug, PartialEq, ToCss)]
+#[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
 pub struct SingleValue(pub u32);
 
 impl Parse for SingleValue {
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<SingleValue, ParseError<'i>> {
         let location = input.current_source_location();
@@ -82,17 +82,17 @@ impl ToGeckoFontFeatureValues for Single
         unsafe {
             array.set_len_pod(1);
         }
         array[0] = self.0 as u32;
     }
 }
 
 /// A @font-feature-values block declaration value that keeps one or two values.
-#[derive(Clone, Debug, PartialEq, ToCss)]
+#[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
 pub struct PairValues(pub u32, pub Option<u32>);
 
 impl Parse for PairValues {
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<PairValues, ParseError<'i>> {
         let location = input.current_source_location();
@@ -126,17 +126,17 @@ impl ToGeckoFontFeatureValues for PairVa
         array[0] = self.0 as u32;
         if let Some(second) = self.1 {
             array[1] = second as u32;
         };
     }
 }
 
 /// A @font-feature-values block declaration value that keeps a list of values.
-#[derive(Clone, Debug, PartialEq, ToCss)]
+#[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
 pub struct VectorValues(#[css(iterable)] pub Vec<u32>);
 
 impl Parse for VectorValues {
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<VectorValues, ParseError<'i>> {
         let mut vec = vec![];
@@ -220,17 +220,17 @@ macro_rules! font_feature_values_blocks 
     (
         blocks = [
             $( #[$doc: meta] $name: tt $ident: ident / $ident_camel: ident / $gecko_enum: ident: $ty: ty, )*
         ]
     ) => {
         /// The [`@font-feature-values`][font-feature-values] at-rule.
         ///
         /// [font-feature-values]: https://drafts.csswg.org/css-fonts-3/#at-font-feature-values-rule
-        #[derive(Clone, Debug, PartialEq)]
+        #[derive(Clone, Debug, PartialEq, ToShmem)]
         pub struct FontFeatureValuesRule {
             /// Font family list for @font-feature-values rule.
             /// Family names cannot contain generic families. FamilyName
             /// also accepts only non-generic names.
             pub family_names: Vec<FamilyName>,
             $(
                 #[$doc]
                 pub $ident: Vec<FFVDeclaration<$ty>>,
--- a/servo/components/style/stylesheets/keyframes_rule.rs
+++ b/servo/components/style/stylesheets/keyframes_rule.rs
@@ -21,17 +21,17 @@ use cssparser::{parse_one_rule, Declarat
 use cssparser::{AtRuleParser, CowRcStr, Parser, ParserInput, QualifiedRuleParser, RuleListParser};
 use servo_arc::Arc;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
 
 /// A [`@keyframes`][keyframes] rule.
 ///
 /// [keyframes]: https://drafts.csswg.org/css-animations/#keyframes
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 pub struct KeyframesRule {
     /// The name of the current animation.
     pub name: KeyframesName,
     /// The keyframes specified for this CSS rule.
     pub keyframes: Vec<Arc<Locked<Keyframe>>>,
     /// Vendor prefix type the @keyframes has.
     pub vendor_prefix: Option<VendorPrefix>,
     /// The line and column of the rule's source code.
@@ -94,17 +94,17 @@ impl DeepCloneWithLock for KeyframesRule
             vendor_prefix: self.vendor_prefix.clone(),
             source_location: self.source_location.clone(),
         }
     }
 }
 
 /// A number from 0 to 1, indicating the percentage of the animation when this
 /// keyframe should run.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToShmem)]
 pub struct KeyframePercentage(pub f32);
 
 impl ::std::cmp::Ord for KeyframePercentage {
     #[inline]
     fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
         // We know we have a number from 0 to 1, so unwrap() here is safe.
         self.0.partial_cmp(&other.0).unwrap()
     }
@@ -145,17 +145,17 @@ impl KeyframePercentage {
             _ => Err(input.new_unexpected_token_error(token)),
         }
     }
 }
 
 /// A keyframes selector is a list of percentages or from/to symbols, which are
 /// converted at parse time to percentages.
 #[css(comma)]
-#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
+#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
 pub struct KeyframeSelector(#[css(iterable)] Vec<KeyframePercentage>);
 
 impl KeyframeSelector {
     /// Return the list of percentages this selector contains.
     #[inline]
     pub fn percentages(&self) -> &[KeyframePercentage] {
         &self.0
     }
@@ -169,17 +169,17 @@ impl KeyframeSelector {
     pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         input
             .parse_comma_separated(KeyframePercentage::parse)
             .map(KeyframeSelector)
     }
 }
 
 /// A keyframe.
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 pub struct Keyframe {
     /// The selector this keyframe was specified from.
     pub selector: KeyframeSelector,
 
     /// The declaration block that was declared inside this keyframe.
     ///
     /// Note that `!important` rules in keyframes don't apply, but we keep this
     /// `Arc` just for convenience.
--- a/servo/components/style/stylesheets/media_rule.rs
+++ b/servo/components/style/stylesheets/media_rule.rs
@@ -16,17 +16,17 @@ use cssparser::SourceLocation;
 use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
 use servo_arc::Arc;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
 /// An [`@media`][media] urle.
 ///
 /// [media]: https://drafts.csswg.org/css-conditional/#at-ruledef-media
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 pub struct MediaRule {
     /// The list of media queries used by this media rule.
     pub media_queries: Arc<Locked<MediaList>>,
     /// The nested rules to this media rule.
     pub rules: Arc<Locked<CssRules>>,
     /// The source position where this media rule was found.
     pub source_location: SourceLocation,
 }
--- a/servo/components/style/stylesheets/mod.rs
+++ b/servo/components/style/stylesheets/mod.rs
@@ -199,17 +199,17 @@ impl fmt::Debug for UrlExtraData {
 // XXX We probably need to figure out whether we should mark Eq here.
 // It is currently marked so because properties::UnparsedValue wants Eq.
 #[cfg(feature = "gecko")]
 impl Eq for UrlExtraData {}
 
 /// A CSS rule.
 ///
 /// TODO(emilio): Lots of spec links should be around.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, ToShmem)]
 #[allow(missing_docs)]
 pub enum CssRule {
     // No Charset here, CSSCharsetRule has been removed from CSSOM
     // https://drafts.csswg.org/cssom/#changes-from-5-december-2013
     Namespace(Arc<Locked<NamespaceRule>>),
     Import(Arc<Locked<ImportRule>>),
     Style(Arc<Locked<StyleRule>>),
     Media(Arc<Locked<MediaRule>>),
--- a/servo/components/style/stylesheets/namespace_rule.rs
+++ b/servo/components/style/stylesheets/namespace_rule.rs
@@ -6,17 +6,17 @@
 
 use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
 use crate::str::CssStringWriter;
 use crate::{Namespace, Prefix};
 use cssparser::SourceLocation;
 use std::fmt::{self, Write};
 
 /// A `@namespace` rule.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, ToShmem)]
 #[allow(missing_docs)]
 pub struct NamespaceRule {
     /// The namespace prefix, and `None` if it's the default Namespace
     pub prefix: Option<Prefix>,
     /// The actual namespace url.
     pub url: Namespace,
     /// The source location this rule was found at.
     pub source_location: SourceLocation,
--- a/servo/components/style/stylesheets/origin.rs
+++ b/servo/components/style/stylesheets/origin.rs
@@ -5,17 +5,17 @@
 //! [CSS cascade origins](https://drafts.csswg.org/css-cascade/#cascading-origins).
 
 use std::marker::PhantomData;
 use std::ops::BitOrAssign;
 
 /// Each style rule has an origin, which determines where it enters the cascade.
 ///
 /// <https://drafts.csswg.org/css-cascade/#cascading-origins>
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, ToShmem)]
 #[repr(u8)]
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 pub enum Origin {
     /// <https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent>
     UserAgent = 1 << 0,
 
     /// <https://drafts.csswg.org/css-cascade/#cascade-origin-user>
     User = 1 << 1,
--- a/servo/components/style/stylesheets/page_rule.rs
+++ b/servo/components/style/stylesheets/page_rule.rs
@@ -20,17 +20,17 @@ use std::fmt::{self, Write};
 ///
 /// This implements only a limited subset of the CSS
 /// 2.2 syntax.
 ///
 /// In this subset, [page selectors][page-selectors] are not implemented.
 ///
 /// [page]: https://drafts.csswg.org/css2/page.html#page-box
 /// [page-selectors]: https://drafts.csswg.org/css2/page.html#page-selectors
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 pub struct PageRule {
     /// The declaration block this page rule contains.
     pub block: Arc<Locked<PropertyDeclarationBlock>>,
     /// The source position this rule was found at.
     pub source_location: SourceLocation,
 }
 
 impl PageRule {
--- a/servo/components/style/stylesheets/rule_list.rs
+++ b/servo/components/style/stylesheets/rule_list.rs
@@ -12,17 +12,17 @@ use crate::stylesheets::rule_parser::{In
 use crate::stylesheets::stylesheet::StylesheetContents;
 use crate::stylesheets::{CssRule, RulesMutateError};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
 use servo_arc::{Arc, RawOffsetArc};
 use std::fmt::{self, Write};
 
 /// A list of CSS rules.
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 pub struct CssRules(pub Vec<CssRule>);
 
 impl CssRules {
     /// Whether this CSS rules is empty.
     pub fn is_empty(&self) -> bool {
         self.0.is_empty()
     }
 }
--- a/servo/components/style/stylesheets/rule_parser.rs
+++ b/servo/components/style/stylesheets/rule_parser.rs
@@ -128,17 +128,17 @@ pub enum State {
     /// We're parsing `@import` rules.
     Imports = 2,
     /// We're parsing `@namespace` rules.
     Namespaces = 3,
     /// We're parsing the main body of the stylesheet.
     Body = 4,
 }
 
-#[derive(Clone, Debug, MallocSizeOf)]
+#[derive(Clone, Debug, MallocSizeOf, ToShmem)]
 /// Vendor prefix.
 pub enum VendorPrefix {
     /// -moz prefix.
     Moz,
     /// -webkit prefix.
     WebKit,
 }
 
--- a/servo/components/style/stylesheets/style_rule.rs
+++ b/servo/components/style/stylesheets/style_rule.rs
@@ -14,17 +14,17 @@ use cssparser::SourceLocation;
 use malloc_size_of::MallocUnconditionalShallowSizeOf;
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use selectors::SelectorList;
 use servo_arc::Arc;
 use std::fmt::{self, Write};
 
 /// A style rule, with selectors and declarations.
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 pub struct StyleRule {
     /// The list of selectors in this rule.
     pub selectors: SelectorList<SelectorImpl>,
     /// The declaration block with the properties it contains.
     pub block: Arc<Locked<PropertyDeclarationBlock>>,
     /// The location in the sheet where it was found.
     pub source_location: SourceLocation,
 }
--- a/servo/components/style/stylesheets/supports_rule.rs
+++ b/servo/components/style/stylesheets/supports_rule.rs
@@ -21,17 +21,17 @@ use servo_arc::Arc;
 use std::ffi::{CStr, CString};
 use std::fmt::{self, Write};
 use std::str;
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
 /// An [`@supports`][supports] rule.
 ///
 /// [supports]: https://drafts.csswg.org/css-conditional-3/#at-supports
-#[derive(Debug)]
+#[derive(Debug, ToShmem)]
 pub struct SupportsRule {
     /// The parsed condition
     pub condition: SupportsCondition,
     /// Child rules
     pub rules: Arc<Locked<CssRules>>,
     /// The result of evaluating the condition
     pub enabled: bool,
     /// The line and column of the rule's source code.
@@ -71,17 +71,17 @@ impl DeepCloneWithLock for SupportsRule 
             source_location: self.source_location.clone(),
         }
     }
 }
 
 /// An @supports condition
 ///
 /// <https://drafts.csswg.org/css-conditional-3/#at-supports>
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, ToShmem)]
 pub enum SupportsCondition {
     /// `not (condition)`
     Not(Box<SupportsCondition>),
     /// `(condition)`
     Parenthesized(Box<SupportsCondition>),
     /// `(condition) and (condition) and (condition) ..`
     And(Vec<SupportsCondition>),
     /// `(condition) or (condition) or (condition) ..`
@@ -300,17 +300,17 @@ impl ToCss for SupportsCondition {
                 name.to_css(dest)?;
                 dest.write_str(")")
             },
             SupportsCondition::FutureSyntax(ref s) => dest.write_str(&s),
         }
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, ToShmem)]
 /// A possibly-invalid CSS selector.
 pub struct RawSelector(pub String);
 
 impl ToCss for RawSelector {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: Write,
     {
@@ -362,17 +362,17 @@ impl RawSelector {
                 }
 
                 Ok(())
             })
             .is_ok()
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, ToShmem)]
 /// A possibly-invalid property declaration
 pub struct Declaration(pub String);
 
 impl ToCss for Declaration {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: Write,
     {
--- a/servo/components/style/stylesheets/viewport_rule.rs
+++ b/servo/components/style/stylesheets/viewport_rule.rs
@@ -75,17 +75,17 @@ macro_rules! declare_viewport_descriptor
     };
 
     (
         [ $( $assigned_variant_name: expr =>
              $assigned_variant: ident($assigned_data: ident) = $assigned_discriminant: expr, )* ]
         [ ]
         $number_of_variants: expr
     ) => {
-        #[derive(Clone, Debug, PartialEq)]
+        #[derive(Clone, Debug, PartialEq, ToShmem)]
         #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
         #[allow(missing_docs)]
         pub enum ViewportDescriptor {
             $(
                 $assigned_variant($assigned_data),
             )+
         }
 
@@ -142,17 +142,17 @@ trait FromMeta: Sized {
 }
 
 /// ViewportLength is a length | percentage | auto | extend-to-zoom
 /// See:
 /// * http://dev.w3.org/csswg/css-device-adapt/#min-max-width-desc
 /// * http://dev.w3.org/csswg/css-device-adapt/#extend-to-zoom
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
-#[derive(Clone, Debug, PartialEq, ToCss)]
+#[derive(Clone, Debug, PartialEq, ToCss, ToShmem)]
 pub enum ViewportLength {
     Specified(NonNegativeLengthPercentageOrAuto),
     ExtendToZoom,
 }
 
 impl FromMeta for ViewportLength {
     fn from_meta(value: &str) -> Option<ViewportLength> {
         macro_rules! specified {
@@ -220,17 +220,17 @@ impl FromMeta for UserZoom {
         })
     }
 }
 
 struct ViewportRuleParser<'a, 'b: 'a> {
     context: &'a ParserContext<'b>,
 }
 
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, ToShmem)]
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 #[allow(missing_docs)]
 pub struct ViewportDescriptorDeclaration {
     pub origin: Origin,
     pub descriptor: ViewportDescriptor,
     pub important: bool,
 }
 
@@ -330,17 +330,17 @@ impl<'a, 'b, 'i> DeclarationParser<'i> f
             "user-zoom" => ok!(UserZoom(UserZoom::parse)),
             "orientation" => ok!(Orientation(Orientation::parse)),
             _ => Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))),
         }
     }
 }
 
 /// A `@viewport` rule.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, ToShmem)]
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 pub struct ViewportRule {
     /// The declarations contained in this @viewport rule.
     pub declarations: Vec<ViewportDescriptorDeclaration>,
 }
 
 /// Whitespace as defined by DEVICE-ADAPT § 9.2
 // TODO: should we just use whitespace as defined by HTML5?
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -220,17 +220,17 @@ impl ToCss for FontFamily {
         for family in iter {
             dest.write_str(", ")?;
             family.to_css(dest)?;
         }
         Ok(())
     }
 }
 
-#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// The name of a font family of choice
 pub struct FamilyName {
     /// Name of the font family
     pub name: Atom,
     /// Syntax of the font family
     pub syntax: FamilyNameSyntax,
 }
@@ -263,17 +263,17 @@ impl ToCss for FamilyName {
                     serialize_identifier(ident, dest)?;
                 }
                 Ok(())
             },
         }
     }
 }
 
-#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// Font family names must either be given quoted as strings,
 /// or unquoted as a sequence of one or more identifiers.
 pub enum FamilyNameSyntax {
     /// The family name was specified in a quoted form, e.g. "Font Name"
     /// or 'Font Name'.
     Quoted,
 
--- a/servo/components/style/values/computed/length.rs
+++ b/servo/components/style/values/computed/length.rs
@@ -603,16 +603,17 @@ impl Size {
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     PartialOrd,
     ToAnimatedValue,
     ToAnimatedZero,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct CSSPixelLength(CSSFloat);
 
 impl CSSPixelLength {
     /// Return a new CSSPixelLength.
     #[inline]
     pub fn new(px: CSSFloat) -> Self {
@@ -804,16 +805,17 @@ pub type NonNegativeLengthOrNumber = Gen
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum ExtremumLength {
     #[parse(aliases = "-moz-max-content")]
     MaxContent,
     #[parse(aliases = "-moz-min-content")]
     MinContent,
     MozFitContent,
--- a/servo/components/style/values/computed/percentage.rs
+++ b/servo/components/style/values/computed/percentage.rs
@@ -22,16 +22,17 @@ use style_traits::{CssWriter, ToCss};
     Default,
     MallocSizeOf,
     PartialEq,
     PartialOrd,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct Percentage(pub CSSFloat);
 
 impl Percentage {
     /// 100%
     #[inline]
     pub fn hundred() -> Self {
--- a/servo/components/style/values/generics/background.rs
+++ b/servo/components/style/values/generics/background.rs
@@ -22,16 +22,17 @@ fn width_and_height_are_auto<L>(
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 pub enum GenericBackgroundSize<LengthPercent> {
     /// `<width> <height>`
     ExplicitSize {
         /// Explicit width.
         width: GenericLengthPercentageOrAuto<LengthPercent>,
         /// Explicit height.
--- a/servo/components/style/values/generics/basic_shape.rs
+++ b/servo/components/style/values/generics/basic_shape.rs
@@ -26,16 +26,17 @@ pub type ClippingShape<BasicShape, Url> 
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum GeometryBox {
     FillBox,
     StrokeBox,
     ViewBox,
     ShapeBox(ShapeBox),
 }
 
@@ -53,16 +54,17 @@ pub type FloatAreaShape<BasicShape, Imag
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum ShapeBox {
     MarginBox,
     BorderBox,
     PaddingBox,
     ContentBox,
 }
 
@@ -74,16 +76,17 @@ pub enum ShapeBox {
     Clone,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
     #[animation(error)]
     ImageOrUrl(ImageOrUrl),
     Shape(BasicShape, Option<ReferenceBox>),
     #[animation(error)]
     Box(ReferenceBox),
     #[css(function)]
@@ -99,40 +102,55 @@ pub enum ShapeSource<BasicShape, Referen
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
-    Inset(#[css(field_bound)] InsetRect<LengthPercentage, NonNegativeLengthPercentage>),
-    Circle(#[css(field_bound)] Circle<H, V, NonNegativeLengthPercentage>),
-    Ellipse(#[css(field_bound)] Ellipse<H, V, NonNegativeLengthPercentage>),
+    Inset(
+        #[css(field_bound)]
+        #[shmem(field_bound)]
+        InsetRect<LengthPercentage, NonNegativeLengthPercentage>,
+    ),
+    Circle(
+        #[css(field_bound)]
+        #[shmem(field_bound)]
+        Circle<H, V, NonNegativeLengthPercentage>,
+    ),
+    Ellipse(
+        #[css(field_bound)]
+        #[shmem(field_bound)]
+        Ellipse<H, V, NonNegativeLengthPercentage>,
+    ),
     Polygon(Polygon<LengthPercentage>),
 }
 
 /// <https://drafts.csswg.org/css-shapes/#funcdef-inset>
 #[allow(missing_docs)]
 #[css(function = "inset")]
 #[derive(
     Animate,
     Clone,
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
+    ToShmem,
 )]
 pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
     pub rect: Rect<LengthPercentage>,
+    #[shmem(field_bound)]
     pub round: BorderRadius<NonNegativeLengthPercentage>,
 }
 
 /// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
 #[allow(missing_docs)]
 #[css(function)]
 #[derive(
     Animate,
@@ -140,16 +158,17 @@ pub struct InsetRect<LengthPercentage, N
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
+    ToShmem,
 )]
 pub struct Circle<H, V, NonNegativeLengthPercentage> {
     pub position: Position<H, V>,
     pub radius: ShapeRadius<NonNegativeLengthPercentage>,
 }
 
 /// <https://drafts.csswg.org/css-shapes/#funcdef-ellipse>
 #[allow(missing_docs)]
@@ -160,16 +179,17 @@ pub struct Circle<H, V, NonNegativeLengt
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
+    ToShmem,
 )]
 pub struct Ellipse<H, V, NonNegativeLengthPercentage> {
     pub position: Position<H, V>,
     pub semiaxis_x: ShapeRadius<NonNegativeLengthPercentage>,
     pub semiaxis_y: ShapeRadius<NonNegativeLengthPercentage>,
 }
 
 /// <https://drafts.csswg.org/css-shapes/#typedef-shape-radius>
@@ -181,16 +201,17 @@ pub struct Ellipse<H, V, NonNegativeLeng
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum ShapeRadius<NonNegativeLengthPercentage> {
     Length(NonNegativeLengthPercentage),
     #[animation(error)]
     ClosestSide,
     #[animation(error)]
     FarthestSide,
 }
@@ -203,16 +224,17 @@ pub enum ShapeRadius<NonNegativeLengthPe
     Clone,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub struct Polygon<LengthPercentage> {
     /// The filling rule for a polygon.
     #[css(skip_if = "fill_is_default")]
     pub fill: FillRule,
     /// A collection of (x, y) coordinates to draw the polygon.
     #[css(iterable)]
     pub coordinates: Vec<PolygonCoord<LengthPercentage>>,
@@ -223,16 +245,17 @@ pub struct Polygon<LengthPercentage> {
     Clone,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercentage);
 
 // https://drafts.csswg.org/css-shapes/#typedef-fill-rule
 // NOTE: Basic shapes spec says that these are the only two values, however
 // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
 // says that it can also be `inherit`
 #[allow(missing_docs)]
@@ -244,16 +267,17 @@ pub struct PolygonCoord<LengthPercentage
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum FillRule {
     Nonzero,
     Evenodd,
 }
 
 /// The path function defined in css-shape-2.
@@ -265,16 +289,17 @@ pub enum FillRule {
     Clone,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub struct Path {
     /// The filling rule for the svg path.
     #[css(skip_if = "fill_is_default")]
     #[animation(constant)]
     pub fill: FillRule,
     /// The svg path data.
     pub path: SVGPathData,
--- a/servo/components/style/values/generics/border.rs
+++ b/servo/components/style/values/generics/border.rs
@@ -7,30 +7,46 @@
 use crate::values::generics::rect::Rect;
 use crate::values::generics::size::Size2D;
 use crate::Zero;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
 /// A generic value for a single side of a `border-image-width` property.
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub enum BorderImageSideWidth<LengthPercentage, Number> {
     /// `<length-or-percentage>`
     Length(LengthPercentage),
     /// `<number>`
     Number(Number),
     /// `auto`
     Auto,
 }
 
 /// A generic value for the `border-image-slice` property.
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct GenericBorderImageSlice<NumberOrPercentage> {
     /// The offsets.
     #[css(field_bound)]
     pub offsets: Rect<NumberOrPercentage>,
     /// Whether to fill the middle part.
     #[css(represents_keyword)]
@@ -48,19 +64,20 @@ pub use self::GenericBorderImageSlice as
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C)]
-pub struct GenericBorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>);
+pub struct GenericBorderCornerRadius<L>(#[css(field_bound)] #[shmem(field_bound)] pub Size2D<L>);
 
 pub use self::GenericBorderCornerRadius as BorderCornerRadius;
 
 impl<L> BorderCornerRadius<L> {
     /// Trivially create a `BorderCornerRadius`.
     pub fn new(w: L, h: L) -> Self {
         BorderCornerRadius(Size2D::new(w, h))
     }
@@ -85,19 +102,20 @@ impl<L: Zero> Zero for BorderCornerRadiu
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(transparent)]
-pub struct BorderSpacing<L>(#[css(field_bound)] pub Size2D<L>);
+pub struct BorderSpacing<L>(#[css(field_bound)] #[shmem(field_bound)] pub Size2D<L>);
 
 impl<L> BorderSpacing<L> {
     /// Trivially create a `BorderCornerRadius`.
     pub fn new(w: L, h: L) -> Self {
         BorderSpacing(Size2D::new(w, h))
     }
 }
 
@@ -110,20 +128,22 @@ impl<L> BorderSpacing<L> {
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct GenericBorderRadius<LengthPercentage> {
     /// The top left radius.
+    #[shmem(field_bound)]
     pub top_left: GenericBorderCornerRadius<LengthPercentage>,
     /// The top right radius.
     pub top_right: GenericBorderCornerRadius<LengthPercentage>,
     /// The bottom right radius.
     pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
     /// The bottom left radius.
     pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
 }
--- a/servo/components/style/values/generics/box.rs
+++ b/servo/components/style/values/generics/box.rs
@@ -13,16 +13,17 @@ use crate::values::animated::ToAnimatedZ
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum VerticalAlign<LengthPercentage> {
     /// `baseline`
     Baseline,
     /// `sub`
     Sub,
     /// `super`
     Super,
@@ -53,17 +54,19 @@ impl<L> VerticalAlign<L> {
 
 impl<L> ToAnimatedZero for VerticalAlign<L> {
     fn to_animated_zero(&self) -> Result<Self, ()> {
         Err(())
     }
 }
 
 /// https://drafts.csswg.org/css-animations/#animation-iteration-count
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub enum AnimationIterationCount<Number> {
     /// A `<number>` value.
     Number(Number),
     /// The `infinite` keyword.
     Infinite,
 }
 
 /// A generic value for the `perspective` property.
@@ -76,16 +79,17 @@ pub enum AnimationIterationCount<Number>
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 pub enum GenericPerspective<NonNegativeLength> {
     /// A non-negative length.
     Length(NonNegativeLength),
     /// The keyword `none`.
     None,
 }
--- a/servo/components/style/values/generics/color.rs
+++ b/servo/components/style/values/generics/color.rs
@@ -1,34 +1,34 @@
 /* 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/. */
 
 //! Generic types for color properties.
 
 /// Ratios representing the contribution of color and currentcolor to
 /// the final color value.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToShmem)]
 pub struct ComplexColorRatios {
     /// Numeric color contribution.
     pub bg: f32,
     /// Foreground color, aka currentcolor, contribution.
     pub fg: f32,
 }
 
 impl ComplexColorRatios {
     /// Ratios representing a `Numeric` color.
     pub const NUMERIC: ComplexColorRatios = ComplexColorRatios { bg: 1., fg: 0. };
     /// Ratios representing the `Foreground` color.
     pub const FOREGROUND: ComplexColorRatios = ComplexColorRatios { bg: 0., fg: 1. };
 }
 
 /// This enum represents a combined color from a numeric color and
 /// the current foreground color (currentcolor keyword).
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToShmem)]
 pub enum Color<RGBA> {
     ///  Numeric RGBA color.
     Numeric(RGBA),
 
     /// The current foreground color.
     Foreground,
 
     /// A linear combination of numeric color and currentcolor.
@@ -85,15 +85,16 @@ impl<RGBA> From<RGBA> for Color<RGBA> {
     MallocSizeOf,
     PartialEq,
     Parse,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum ColorOrAuto<C> {
     /// A `<color>
     Color(C),
     /// `auto`
     Auto,
 }
--- a/servo/components/style/values/generics/column.rs
+++ b/servo/components/style/values/generics/column.rs
@@ -14,16 +14,17 @@
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum ColumnCount<PositiveInteger> {
     /// A positive integer.
     Integer(PositiveInteger),
     /// The keyword `auto`.
     #[animation(error)]
     Auto,
 }
--- a/servo/components/style/values/generics/counters.rs
+++ b/servo/components/style/values/generics/counters.rs
@@ -9,27 +9,37 @@ use crate::computed_values::list_style_t
 #[cfg(feature = "gecko")]
 use crate::values::generics::CounterStyleOrNone;
 #[cfg(feature = "gecko")]
 use crate::values::specified::Attr;
 use crate::values::CustomIdent;
 use std::ops::Deref;
 
 /// A name / value pair for counters.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct CounterPair<Integer> {
     /// The name of the counter.
     pub name: CustomIdent,
     /// The value of the counter / increment / etc.
     pub value: Integer,
 }
 
 /// A generic value for the `counter-increment` property.
 #[derive(
-    Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Debug,
+    Default,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub struct CounterIncrement<I>(Counters<I>);
 
 impl<I> CounterIncrement<I> {
     /// Returns a new value for `counter-increment`.
     #[inline]
     pub fn new(counters: Vec<CounterPair<I>>) -> Self {
         CounterIncrement(Counters(counters.into_boxed_slice()))
@@ -42,17 +52,25 @@ impl<I> Deref for CounterIncrement<I> {
     #[inline]
     fn deref(&self) -> &Self::Target {
         &(self.0).0
     }
 }
 
 /// A generic value for the `counter-set` and `counter-reset` properties.
 #[derive(
-    Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Debug,
+    Default,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub struct CounterSetOrReset<I>(Counters<I>);
 
 impl<I> CounterSetOrReset<I> {
     /// Returns a new value for `counter-set` / `counter-reset`.
     #[inline]
     pub fn new(counters: Vec<CounterPair<I>>) -> Self {
         CounterSetOrReset(Counters(counters.into_boxed_slice()))
@@ -66,17 +84,19 @@ impl<I> Deref for CounterSetOrReset<I> {
     fn deref(&self) -> &Self::Target {
         &(self.0).0
     }
 }
 
 /// A generic value for lists of counters.
 ///
 /// Keyword `none` is represented by an empty vector.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct Counters<I>(#[css(iterable, if_empty = "none")] Box<[CounterPair<I>]>);
 
 impl<I> Default for Counters<I> {
     #[inline]
     fn default() -> Self {
         Counters(vec![].into_boxed_slice())
     }
 }
@@ -97,17 +117,19 @@ fn is_decimal(counter_type: &CounterStyl
 #[inline]
 fn is_decimal(counter_type: &CounterStyleType) -> bool {
     *counter_type == CounterStyleOrNone::decimal()
 }
 
 /// The specified value for the `content` property.
 ///
 /// https://drafts.csswg.org/css-content/#propdef-content
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub enum Content<ImageUrl> {
     /// `normal` reserved keyword.
     Normal,
     /// `none` reserved keyword.
     None,
     /// `-moz-alt-content`.
     #[cfg(feature = "gecko")]
     MozAltContent,
@@ -119,17 +141,19 @@ impl<ImageUrl> Content<ImageUrl> {
     /// Set `content` property to `normal`.
     #[inline]
     pub fn normal() -> Self {
         Content::Normal
     }
 }
 
 /// Items for the `content` property.
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub enum ContentItem<ImageUrl> {
     /// Literal string content.
     String(Box<str>),
     /// `counter(name, style)`.
     #[css(comma, function)]
     Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyleType),
     /// `counters(name, separator, style)`.
     #[css(comma, function)]
--- a/servo/components/style/values/generics/easing.rs
+++ b/servo/components/style/values/generics/easing.rs
@@ -5,17 +5,25 @@
 //! Generic types for CSS Easing Functions.
 //! https://drafts.csswg.org/css-easing/#timing-functions
 
 use crate::parser::ParserContext;
 use crate::values::CSSFloat;
 
 /// A generic easing function.
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 #[value_info(ty = "TIMING_FUNCTION")]
 #[repr(u8, C)]
 pub enum TimingFunction<Integer, Number> {
     /// `linear | ease | ease-in | ease-out | ease-in-out`
     Keyword(TimingKeyword),
     /// `cubic-bezier(<number>, <number>, <number>, <number>)`
     #[allow(missing_docs)]
@@ -41,16 +49,17 @@ pub enum TimingFunction<Integer, Number>
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum TimingKeyword {
     Linear,
     Ease,
     EaseIn,
     EaseOut,
     EaseInOut,
@@ -64,17 +73,19 @@ fn step_position_jump_enabled(_context: 
 
 #[cfg(feature = "servo")]
 fn step_position_jump_enabled(_context: &ParserContext) -> bool {
     false
 }
 
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss, ToShmem,
+)]
 #[repr(u8)]
 pub enum StepPosition {
     #[parse(condition = "step_position_jump_enabled")]
     JumpStart,
     #[parse(condition = "step_position_jump_enabled")]
     JumpEnd,
     #[parse(condition = "step_position_jump_enabled")]
     JumpNone,
--- a/servo/components/style/values/generics/effects.rs
+++ b/servo/components/style/values/generics/effects.rs
@@ -11,16 +11,17 @@
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToCss,
+    ToShmem,
 )]
 pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
     /// The base shadow.
     pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
     /// The spread radius.
     pub spread: ShapeLength,
     /// Whether this is an inset box shadow.
     #[animation(constant)]
@@ -36,16 +37,17 @@ pub struct BoxShadow<Color, SizeLength, 
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum Filter<Angle, Factor, Length, DropShadow, Url> {
     /// `blur(<length>)`
     #[css(function)]
     Blur(Length),
     /// `brightness(<factor>)`
     #[css(function)]
     Brightness(Factor),
@@ -88,16 +90,17 @@ pub enum Filter<Angle, Factor, Length, D
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToCss,
+    ToShmem,
 )]
 pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
     /// Color.
     pub color: Color,
     /// Horizontal radius.
     pub horizontal: SizeLength,
     /// Vertical radius.
     pub vertical: SizeLength,
--- a/servo/components/style/values/generics/flex.rs
+++ b/servo/components/style/values/generics/flex.rs
@@ -14,16 +14,17 @@
     Debug,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C)]
 pub enum GenericFlexBasis<S> {
     /// `content`
     Content,
     /// `<width>`
     Size(S),
 }
--- a/servo/components/style/values/generics/font.rs
+++ b/servo/components/style/values/generics/font.rs
@@ -10,17 +10,19 @@ use byteorder::{BigEndian, ReadBytesExt}
 use cssparser::Parser;
 use num_traits::One;
 use std::fmt::{self, Write};
 use std::io::Cursor;
 use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
 use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
 
 /// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct FeatureTagValue<Integer> {
     /// A four-character tag, packed into a u32 (one byte per character).
     pub tag: FontTag,
     /// The actual value.
     pub value: Integer,
 }
 
 impl<Integer> ToCss for FeatureTagValue<Integer>
@@ -51,28 +53,31 @@ where
     ComputeSquaredDistance,
     Debug,
     Eq,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub struct VariationValue<Number> {
     /// A four-character tag, packed into a u32 (one byte per character).
     #[animation(constant)]
     pub tag: FontTag,
     /// The actual value.
     pub value: Number,
 }
 
 /// A value both for font-variation-settings and font-feature-settings.
 #[css(comma)]
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct FontSettings<T>(#[css(if_empty = "normal", iterable)] pub Box<[T]>);
 
 impl<T> FontSettings<T> {
     /// Default value of font settings as `normal`.
     #[inline]
     pub fn normal() -> Self {
         FontSettings(vec![].into_boxed_slice())
     }
@@ -98,17 +103,19 @@ impl<T: Parse> Parse for FontSettings<T>
 }
 
 /// A font four-character tag, represented as a u32 for convenience.
 ///
 /// See:
 ///   https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def
 ///   https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings
 ///
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct FontTag(pub u32);
 
 impl ToCss for FontTag {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: Write,
     {
         use byteorder::{BigEndian, ByteOrder};
@@ -144,16 +151,17 @@ impl Parse for FontTag {
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     ToAnimatedValue,
     ToAnimatedZero,
     ToCss,
+    ToShmem,
 )]
 /// Additional information for keyword-derived font sizes.
 pub struct KeywordInfo<Length> {
     /// The keyword used
     pub kw: KeywordSize,
     /// A factor to be multiplied by the computed size of the keyword
     #[css(skip)]
     pub factor: f32,
@@ -200,16 +208,17 @@ impl<L> SpecifiedValueInfo for KeywordIn
     Debug,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToCss,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 pub enum KeywordSize {
     #[css(keyword = "xx-small")]
     XXSmall,
     XSmall,
     Small,
     Medium,
@@ -249,16 +258,17 @@ impl Default for KeywordSize {
     Copy,
     Debug,
     Hash,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
+    ToShmem,
 )]
 pub enum FontStyle<Angle> {
     #[animation(error)]
     Normal,
     #[animation(error)]
     Italic,
     #[value_info(starts_with_keyword)]
     Oblique(Angle),
--- a/servo/components/style/values/generics/gecko.rs
+++ b/servo/components/style/values/generics/gecko.rs
@@ -2,17 +2,17 @@
  * 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/. */
 
 //! Generic types for legacy Gecko-only properties that should probably be
 //! unshipped at some point in the future.
 
 /// A generic value for scroll snap points.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem)]
 pub enum ScrollSnapPoint<LengthPercentage> {
     /// `none`
     None,
     /// `repeat(<length-or-percentage>)`
     #[css(function)]
     Repeat(LengthPercentage),
 }
 
--- a/servo/components/style/values/generics/grid.rs
+++ b/servo/components/style/values/generics/grid.rs
@@ -13,17 +13,19 @@ use crate::values::{CSSFloat, CustomIden
 use cssparser::Parser;
 use std::fmt::{self, Write};
 use std::{mem, usize};
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
 /// A `<grid-line>` type.
 ///
 /// <https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line>
-#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct GridLine<Integer> {
     /// Flag to check whether it's a `span` keyword.
     pub is_span: bool,
     /// A custom identifier for named lines.
     ///
     /// <https://drafts.csswg.org/css-grid/#grid-placement-slot>
     pub ident: Option<CustomIdent>,
     /// Denotes the nth grid line from grid item's placement.
@@ -157,29 +159,38 @@ impl Parse for GridLine<specified::Integ
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum TrackKeyword {
     Auto,
     MaxContent,
     MinContent,
 }
 
 /// A track breadth for explicit grid track sizing. It's generic solely to
 /// avoid re-implementing it for the computed type.
 ///
 /// <https://drafts.csswg.org/css-grid/#typedef-track-breadth>
 #[derive(
-    Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Animate,
+    Clone,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub enum TrackBreadth<L> {
     /// The generic type is almost always a non-negative `<length-percentage>`
     Breadth(L),
     /// A flex fraction specified in `fr` units.
     #[css(dimension)]
     Fr(CSSFloat),
     /// One of the track-sizing keywords (`auto`, `min-content`, `max-content`)
@@ -195,17 +206,17 @@ impl<L> TrackBreadth<L> {
         matches!(*self, TrackBreadth::Breadth(..))
     }
 }
 
 /// A `<track-size>` type for explicit grid track sizing. Like `<track-breadth>`, this is
 /// generic only to avoid code bloat. It only takes `<length-percentage>`
 ///
 /// <https://drafts.csswg.org/css-grid/#typedef-track-size>
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)]
 pub enum TrackSize<L> {
     /// A flexible `<track-breadth>`
     Breadth(TrackBreadth<L>),
     /// A `minmax` function for a range over an inflexible `<track-breadth>`
     /// and a flexible `<track-breadth>`
     ///
     /// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax>
     #[css(function)]
@@ -353,17 +364,17 @@ where
     }
 
     Ok(())
 }
 
 /// The initial argument of the `repeat` function.
 ///
 /// <https://drafts.csswg.org/css-grid/#typedef-track-repeat>
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub enum RepeatCount<Integer> {
     /// A positive integer. This is allowed only for `<track-repeat>` and `<fixed-repeat>`
     Number(Integer),
     /// An `<auto-fill>` keyword allowed only for `<auto-repeat>`
     AutoFill,
     /// An `<auto-fit>` keyword allowed only for `<auto-repeat>`
     AutoFit,
 }
@@ -388,17 +399,17 @@ impl Parse for RepeatCount<specified::In
         }
     }
 }
 
 /// The structure containing `<line-names>` and `<track-size>` values.
 ///
 /// It can also hold `repeat()` function parameters, which expands into the respective
 /// values in its computed form.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem)]
 #[css(function = "repeat")]
 pub struct TrackRepeat<L, I> {
     /// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`)
     pub count: RepeatCount<I>,
     /// `<line-names>` accompanying `<track_size>` values.
     ///
     /// If there's no `<line-names>`, then it's represented by an empty vector.
     /// For N `<track-size>` values, there will be N+1 `<line-names>`, and so this vector's
@@ -477,29 +488,37 @@ impl<L: Clone> TrackRepeat<L, specified:
                 line_names: self.line_names.clone(),
             }
         }
     }
 }
 
 /// Track list values. Can be <track-size> or <track-repeat>
 #[derive(
-    Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Animate,
+    Clone,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub enum TrackListValue<LengthPercentage, Integer> {
     /// A <track-size> value.
     TrackSize(#[animation(field_bound)] TrackSize<LengthPercentage>),
     /// A <track-repeat> value.
     TrackRepeat(#[animation(field_bound)] TrackRepeat<LengthPercentage, Integer>),
 }
 
 /// The type of a `<track-list>` as determined during parsing.
 ///
 /// <https://drafts.csswg.org/css-grid/#typedef-track-list>
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToShmem)]
 pub enum TrackListType {
     /// [`<auto-track-list>`](https://drafts.csswg.org/css-grid/#typedef-auto-track-list)
     ///
     /// If this type exists, then the value at the index in `line_names` field in `TrackList`
     /// has the `<line-names>?` list that comes before `<auto-repeat>`. If it's a specified value,
     /// then the `repeat()` function (that follows the line names list) is also at the given index
     /// in `values` field. On the contrary, if it's a computed value, then the `repeat()` function
     /// is in the `auto_repeat` field.
@@ -511,17 +530,17 @@ pub enum TrackListType {
     /// Note that this is a subset of the normal `<track-list>`, and so it could be used in place
     /// of the latter.
     Explicit,
 }
 
 /// A grid `<track-list>` type.
 ///
 /// <https://drafts.csswg.org/css-grid/#typedef-track-list>
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)]
 pub struct TrackList<LengthPercentage, Integer> {
     /// The type of this `<track-list>` (auto, explicit or general).
     ///
     /// In order to avoid parsing the same value multiple times, this does a single traversal
     /// and arrives at the type of value it has parsed (or bails out gracefully with an error).
     #[css(skip)]
     pub list_type: TrackListType,
     /// A vector of `<track-size> | <track-repeat>` values.
@@ -584,17 +603,19 @@ impl<L: ToCss, I: ToCss> ToCss for Track
         Ok(())
     }
 }
 
 /// The `<line-name-list>` for subgrids.
 ///
 /// `subgrid [ <line-names> | repeat(<positive-integer> | auto-fill, <line-names>+) ]+`
 /// Old spec: https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-line-name-list
-#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct LineNameList {
     /// The optional `<line-name-list>`
     pub names: Box<[Box<[CustomIdent]>]>,
     /// Indicates the line name that requires `auto-fill`
     pub fill_idx: Option<u32>,
 }
 
 impl Parse for LineNameList {
@@ -690,25 +711,34 @@ impl ToCss for LineNameList {
         Ok(())
     }
 }
 
 /// Variants for `<grid-template-rows> | <grid-template-columns>`
 /// Subgrid deferred to Level 2 spec due to lack of implementation.
 /// But it's implemented in gecko, so we have to as well.
 #[derive(
-    Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Animate,
+    Clone,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub enum GridTemplateComponent<L, I> {
     /// `none` value.
     None,
     /// The grid `<track-list>`
     TrackList(
         #[animation(field_bound)]
         #[compute(field_bound)]
+        #[shmem(field_bound)]
         TrackList<L, I>,
     ),
     /// A `subgrid <line-name-list>?`
     /// TODO: Support animations for this after subgrid is addressed in [grid-2] spec.
     #[animation(error)]
     Subgrid(LineNameList),
 }
 
--- a/servo/components/style/values/generics/image.rs
+++ b/servo/components/style/values/generics/image.rs
@@ -11,17 +11,17 @@ use crate::values::serialize_atom_identi
 use crate::Atom;
 use servo_arc::Arc;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
 /// An [image].
 ///
 /// [image]: https://drafts.csswg.org/css-images/#image-values
-#[derive(Clone, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(Clone, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem)]
 pub enum Image<Gradient, MozImageRect, ImageUrl> {
     /// A `<url()>` image.
     Url(ImageUrl),
     /// A `<gradient>` image.  Gradients are rather large, and not nearly as
     /// common as urls, so we box them here to keep the size of this enum sane.
     Gradient(Box<Gradient>),
     /// A `-moz-image-rect` image.  Also fairly large and rare.
     Rect(Box<MozImageRect>),
@@ -31,105 +31,107 @@ pub enum Image<Gradient, MozImageRect, I
     /// A paint worklet image.
     /// <https://drafts.css-houdini.org/css-paint-api/>
     #[cfg(feature = "servo")]
     PaintWorklet(PaintWorklet),
 }
 
 /// A CSS gradient.
 /// <https://drafts.csswg.org/css-images/#gradients>
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToShmem)]
 pub struct Gradient<LineDirection, Length, LengthPercentage, Position, Color, Angle> {
     /// Gradients can be linear or radial.
     pub kind: GradientKind<LineDirection, Length, LengthPercentage, Position, Angle>,
     /// The color stops and interpolation hints.
     pub items: Vec<GradientItem<Color, LengthPercentage>>,
     /// True if this is a repeating gradient.
     pub repeating: bool,
     /// Compatibility mode.
     pub compat_mode: CompatMode,
 }
 
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToShmem)]
 /// Whether we used the modern notation or the compatibility `-webkit`, `-moz` prefixes.
 pub enum CompatMode {
     /// Modern syntax.
     Modern,
     /// `-webkit` prefix.
     WebKit,
     /// `-moz` prefix
     Moz,
 }
 
 /// A gradient kind.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToShmem)]
 pub enum GradientKind<LineDirection, Length, LengthPercentage, Position, Angle> {
     /// A linear gradient.
     Linear(LineDirection),
     /// A radial gradient.
     Radial(
         EndingShape<Length, LengthPercentage>,
         Position,
         Option<Angle>,
     ),
 }
 
 /// A radial gradient's ending shape.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub enum EndingShape<Length, LengthPercentage> {
     /// A circular gradient.
     Circle(Circle<Length>),
     /// An elliptic gradient.
     Ellipse(Ellipse<LengthPercentage>),
 }
 
 /// A circle shape.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToShmem)]
 pub enum Circle<Length> {
     /// A circle radius.
     Radius(Length),
     /// A circle extent.
     Extent(ShapeExtent),
 }
 
 /// An ellipse shape.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub enum Ellipse<LengthPercentage> {
     /// An ellipse pair of radii.
     Radii(LengthPercentage, LengthPercentage),
     /// An ellipse extent.
     Extent(ShapeExtent),
 }
 
 /// <https://drafts.csswg.org/css-images/#typedef-extent-keyword>
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss, ToShmem,
+)]
 pub enum ShapeExtent {
     ClosestSide,
     FarthestSide,
     ClosestCorner,
     FarthestCorner,
     Contain,
     Cover,
 }
 
 /// A gradient item.
 /// <https://drafts.csswg.org/css-images-4/#color-stop-syntax>
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub enum GradientItem<Color, LengthPercentage> {
     /// A color stop.
     ColorStop(ColorStop<Color, LengthPercentage>),
     /// An interpolation hint.
     InterpolationHint(LengthPercentage),
 }
 
 /// A color stop.
 /// <https://drafts.csswg.org/css-images/#typedef-color-stop-list>
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct ColorStop<Color, LengthPercentage> {
     /// The color of this stop.
     pub color: Color,
     /// The position of this stop.
     pub position: Option<LengthPercentage>,
 }
 
 /// Specified values for a paint worklet.
@@ -162,17 +164,19 @@ impl ToCss for PaintWorklet {
     }
 }
 
 /// Values for `moz-image-rect`.
 ///
 /// `-moz-image-rect(<uri>, top, right, bottom, left);`
 #[allow(missing_docs)]
 #[css(comma, function)]
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct MozImageRect<NumberOrPercentage, MozImageRectUrl> {
     pub url: MozImageRectUrl,
     pub top: NumberOrPercentage,
     pub right: NumberOrPercentage,
     pub bottom: NumberOrPercentage,
     pub left: NumberOrPercentage,
 }
 
--- a/servo/components/style/values/generics/length.rs
+++ b/servo/components/style/values/generics/length.rs
@@ -21,16 +21,17 @@ use style_traits::ParseError;
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 pub enum GenericLengthPercentageOrAuto<LengthPercent> {
     LengthPercentage(LengthPercent),
     Auto,
 }
 
 pub use self::GenericLengthPercentageOrAuto as LengthPercentageOrAuto;
@@ -104,16 +105,17 @@ impl<LengthPercentage: Parse> Parse for 
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 pub enum GenericSize<LengthPercent> {
     LengthPercentage(LengthPercent),
     Auto,
     #[cfg(feature = "gecko")]
     #[animation(error)]
     ExtremumLength(ExtremumLength),
@@ -145,16 +147,17 @@ impl<LengthPercentage> Size<LengthPercen
     Copy,
     Debug,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 pub enum GenericMaxSize<LengthPercent> {
     LengthPercentage(LengthPercent),
     None,
     #[cfg(feature = "gecko")]
     #[animation(error)]
     ExtremumLength(ExtremumLength),
@@ -180,16 +183,17 @@ impl<LengthPercentage> MaxSize<LengthPer
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 pub enum GenericLengthOrNumber<L, N> {
     /// A number.
     ///
     /// NOTE: Numbers need to be before lengths, in order to parse them
     /// first, since `0` should be a number, not the `0px` length.
     Number(N),
--- a/servo/components/style/values/generics/mod.rs
+++ b/servo/components/style/values/generics/mod.rs
@@ -38,17 +38,19 @@ pub mod svg;
 pub mod text;
 pub mod transform;
 pub mod ui;
 pub mod url;
 
 // https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss, ToShmem,
+)]
 pub enum SymbolsType {
     Cyclic,
     Numeric,
     Alphabetic,
     Symbolic,
     Fixed,
 }
 
@@ -80,17 +82,17 @@ impl SymbolsType {
     }
 }
 
 /// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style>
 ///
 /// Since wherever <counter-style> is used, 'none' is a valid value as
 /// well, we combine them into one type to make code simpler.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub enum CounterStyleOrNone {
     /// `none`
     None,
     /// `<counter-style-name>`
     Name(CustomIdent),
     /// `symbols()`
     #[css(function)]
     Symbols(SymbolsType, Symbols),
@@ -168,16 +170,17 @@ impl SpecifiedValueInfo for CounterStyle
     Hash,
     MallocSizeOf,
     PartialEq,
     PartialOrd,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(transparent)]
 pub struct NonNegative<T>(pub T);
 
 impl<T: Add<Output = T>> Add<NonNegative<T>> for NonNegative<T> {
     type Output = Self;
 
     fn add(self, other: Self) -> Self {
@@ -205,16 +208,17 @@ impl<T: Zero> Zero for NonNegative<T> {
     Debug,
     MallocSizeOf,
     PartialEq,
     PartialOrd,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub struct GreaterThanOrEqualToOne<T>(pub T);
 
 /// A clip rect for clip and image-region
 #[allow(missing_docs)]
 #[derive(
     Clone,
     ComputeSquaredDistance,
@@ -222,16 +226,17 @@ pub struct GreaterThanOrEqualToOne<T>(pu
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[css(function = "rect", comma)]
 pub struct ClipRect<LengthOrAuto> {
     pub top: LengthOrAuto,
     pub right: LengthOrAuto,
     pub bottom: LengthOrAuto,
     pub left: LengthOrAuto,
 }
--- a/servo/components/style/values/generics/position.rs
+++ b/servo/components/style/values/generics/position.rs
@@ -13,16 +13,17 @@
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct GenericPosition<H, V> {
     /// The horizontal component of position.
     pub horizontal: H,
     /// The vertical component of position.
     pub vertical: V,
 }
@@ -48,16 +49,17 @@ impl<H, V> Position<H, V> {
     Debug,
     MallocSizeOf,
     PartialEq,
     Parse,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 pub enum GenericZIndex<I> {
     /// An integer value.
     Integer(I),
     /// The keyword `auto`.
     Auto,
 }
--- a/servo/components/style/values/generics/rect.rs
+++ b/servo/components/style/values/generics/rect.rs
@@ -17,16 +17,17 @@ use style_traits::{CssWriter, ParseError
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct Rect<T>(pub T, pub T, pub T, pub T);
 
 impl<T> Rect<T> {
     /// Returns a new `Rect<T>` value.
     pub fn new(first: T, second: T, third: T, fourth: T) -> Self {
         Rect(first, second, third, fourth)
--- a/servo/components/style/values/generics/size.rs
+++ b/servo/components/style/values/generics/size.rs
@@ -19,16 +19,17 @@ use style_traits::{CssWriter, ParseError
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToAnimatedValue,
     ToComputedValue,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 #[repr(C)]
 pub struct Size2D<L> {
     pub width: L,
     pub height: L,
 }
 
--- a/servo/components/style/values/generics/svg.rs
+++ b/servo/components/style/values/generics/svg.rs
@@ -19,16 +19,17 @@ use style_traits::{ParseError, StylePars
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub struct SVGPaint<ColorType, UrlPaintServer> {
     /// The paint source
     pub kind: SVGPaintKind<ColorType, UrlPaintServer>,
     /// The fallback color. It would be empty, the `none` keyword or <color>.
     pub fallback: Option<Either<ColorType, None_>>,
 }
 
@@ -45,16 +46,17 @@ pub struct SVGPaint<ColorType, UrlPaintS
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum SVGPaintKind<ColorType, UrlPaintServer> {
     /// `none`
     #[animation(error)]
     None,
     /// `<color>`
     Color(ColorType),
     /// `url(...)`
@@ -137,16 +139,17 @@ impl<ColorType: Parse, UrlPaintServer: P
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum SVGLength<L> {
     /// `<length> | <percentage> | <number>`
     LengthPercentage(L),
     /// `context-value`
     #[animation(error)]
     ContextValue,
 }
@@ -157,16 +160,17 @@ pub enum SVGLength<L> {
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum SVGStrokeDashArray<L> {
     /// `[ <length> | <percentage> | <number> ]#`
     #[css(comma)]
     Values(#[css(if_empty = "none", iterable)] Vec<L>),
     /// `context-value`
     ContextValue,
 }
@@ -181,16 +185,17 @@ pub enum SVGStrokeDashArray<L> {
     Debug,
     MallocSizeOf,
     PartialEq,
     Parse,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum SVGOpacity<OpacityType> {
     /// `<opacity-value>`
     Opacity(OpacityType),
     /// `context-fill-opacity`
     #[animation(error)]
     ContextFillOpacity,
     /// `context-stroke-opacity`
--- a/servo/components/style/values/generics/text.rs
+++ b/servo/components/style/values/generics/text.rs
@@ -6,17 +6,25 @@
 
 use crate::parser::ParserContext;
 use crate::values::animated::ToAnimatedZero;
 use cssparser::Parser;
 use style_traits::ParseError;
 
 /// A generic value for the `initial-letter` property.
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub enum InitialLetter<Number, Integer> {
     /// `normal`
     Normal,
     /// `<number> <integer>?`
     Specified(Number, Option<Integer>),
 }
 
@@ -24,17 +32,19 @@ impl<N, I> InitialLetter<N, I> {
     /// Returns `normal`.
     #[inline]
     pub fn normal() -> Self {
         InitialLetter::Normal
     }
 }
 
 /// A generic spacing value for the `letter-spacing` and `word-spacing` properties.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
+)]
 pub enum Spacing<Value> {
     /// `normal`
     Normal,
     /// `<value>`
     Value(Value),
 }
 
 impl<Value> Spacing<Value> {
@@ -76,16 +86,17 @@ fn line_height_moz_block_height_enabled(
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToCss,
+    ToShmem,
     Parse,
 )]
 #[repr(C, u8)]
 pub enum GenericLineHeight<N, L> {
     /// `normal`
     Normal,
     /// `-moz-block-height`
     #[cfg(feature = "gecko")]
--- a/servo/components/style/values/generics/transform.rs
+++ b/servo/components/style/values/generics/transform.rs
@@ -14,33 +14,41 @@ use crate::Zero;
 use app_units::Au;
 use euclid::{self, Rect, Transform3D};
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
 /// A generic 2D transformation matrix.
 #[allow(missing_docs)]
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 #[css(comma, function)]
 pub struct Matrix<T> {
     pub a: T,
     pub b: T,
     pub c: T,
     pub d: T,
     pub e: T,
     pub f: T,
 }
 
 #[allow(missing_docs)]
 #[cfg_attr(rustfmt, rustfmt_skip)]
 #[css(comma, function = "matrix3d")]
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToComputedValue, ToCss)]
+         ToComputedValue, ToCss, ToShmem)]
 pub struct Matrix3D<T> {
     pub m11: T, pub m12: T, pub m13: T, pub m14: T,
     pub m21: T, pub m22: T, pub m23: T, pub m24: T,
     pub m31: T, pub m32: T, pub m33: T, pub m34: T,
     pub m41: T, pub m42: T, pub m43: T, pub m44: T,
 }
 
 #[cfg_attr(rustfmt, rustfmt_skip)]
@@ -77,16 +85,17 @@ impl<T: Into<f64>> From<Matrix3D<T>> for
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct GenericTransformOrigin<H, V, Depth> {
     /// The horizontal origin.
     pub horizontal: H,
     /// The vertical origin.
     pub vertical: V,
     /// The depth.
@@ -105,17 +114,19 @@ impl<H, V, D> TransformOrigin<H, V, D> {
         }
     }
 }
 
 fn is_same<N: PartialEq>(x: &N, y: &N) -> bool {
     x == y
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 /// A single operation in the list of a `transform` value
 pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage>
 where
     Angle: Zero,
     LengthPercentage: Zero,
     Number: PartialEq,
 {
     /// Represents a 2D 2x3 matrix.
@@ -210,17 +221,19 @@ where
     #[css(comma, function = "accumulatematrix")]
     AccumulateMatrix {
         from_list: Transform<TransformOperation<Angle, Number, Length, Integer, LengthPercentage>>,
         to_list: Transform<TransformOperation<Angle, Number, Length, Integer, LengthPercentage>>,
         count: Integer,
     },
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 /// A value of the `transform` property
 pub struct Transform<T>(#[css(if_empty = "none", iterable)] pub Vec<T>);
 
 impl<Angle, Number, Length, Integer, LengthPercentage>
     TransformOperation<Angle, Number, Length, Integer, LengthPercentage>
 where
     Angle: Zero,
     LengthPercentage: Zero,
@@ -532,17 +545,25 @@ pub fn get_normalized_vector_and_angle<T
         (0., 0., 1., T::zero())
     } else {
         let vector = vector.robust_normalize();
         (vector.x, vector.y, vector.z, angle)
     }
 }
 
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToAnimatedZero,
+    ToComputedValue,
+    ToShmem,
 )]
 /// A value of the `Rotate` property
 ///
 /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
 pub enum Rotate<Number, Angle> {
     /// 'none'
     None,
     /// '<angle>'
@@ -594,17 +615,25 @@ where
                 dest.write_char(' ')?;
                 angle.to_css(dest)
             },
         }
     }
 }
 
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToAnimatedZero,
+    ToComputedValue,
+    ToShmem,
 )]
 /// A value of the `Scale` property
 ///
 /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
 pub enum Scale<Number> {
     /// 'none'
     None,
     /// '<number>{1,2}'
@@ -643,16 +672,17 @@ impl<Number: ToCss + PartialEq> ToCss fo
     Clone,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 /// A value of the `translate` property
 ///
 /// https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization:
 ///
 /// If a 2d translation is specified, the property must serialize with only one
 /// or two values (per usual, if the second value is 0px, the default, it must
 /// be omitted when serializing).
@@ -675,17 +705,26 @@ where
         #[css(skip_if = "Zero::is_zero")] LengthPercentage,
     ),
     /// '<length-percentage> <length-percentage> <length>'
     Translate3D(LengthPercentage, LengthPercentage, Length),
 }
 
 #[allow(missing_docs)]
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    Parse,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub enum TransformStyle {
     #[cfg(feature = "servo")]
     Auto,
     Flat,
     #[css(keyword = "preserve-3d")]
     Preserve3d,
 }
--- a/servo/components/style/values/generics/ui.rs
+++ b/servo/components/style/values/generics/ui.rs
@@ -6,17 +6,17 @@
 
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 use values::specified::ui::CursorKind;
 
 /// A generic value for the `cursor` property.
 ///
 /// https://drafts.csswg.org/css-ui/#cursor
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem)]
 pub struct Cursor<Image> {
     /// The parsed images for the cursor.
     pub images: Box<[Image]>,
     /// The kind of the cursor [default | help | ...].
     pub keyword: CursorKind,
 }
 
 impl<Image> Cursor<Image> {
@@ -39,17 +39,17 @@ impl<Image: ToCss> ToCss for Cursor<Imag
             image.to_css(dest)?;
             dest.write_str(", ")?;
         }
         self.keyword.to_css(dest)
     }
 }
 
 /// A generic value for item of `image cursors`.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem)]
 pub struct CursorImage<ImageUrl, Number> {
     /// The url to parse images from.
     pub url: ImageUrl,
     /// The <x> and <y> coordinates.
     pub hotspot: Option<(Number, Number)>,
 }
 
 impl<ImageUrl: ToCss, Number: ToCss> ToCss for CursorImage<ImageUrl, Number> {
@@ -79,16 +79,17 @@ impl<ImageUrl: ToCss, Number: ToCss> ToC
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum ScrollbarColor<Color> {
     /// `auto`
     Auto,
     /// `<color>{2}`
     Colors {
         /// First `<color>`, for color of the scrollbar thumb.
         thumb: Color,
--- a/servo/components/style/values/generics/url.rs
+++ b/servo/components/style/values/generics/url.rs
@@ -13,16 +13,17 @@
     MallocSizeOf,
     PartialEq,
     Parse,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum UrlOrNone<Url> {
     /// `none`
     None,
     /// `A URL`
     Url(Url),
 }
 
--- a/servo/components/style/values/mod.rs
+++ b/servo/components/style/values/mod.rs
@@ -129,16 +129,17 @@ impl Parse for Impossible {
     MallocSizeOf,
     PartialEq,
     Parse,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum Either<A, B> {
     /// The first value.
     First(A),
     /// The second kind of value.
     Second(B),
 }
 
@@ -147,17 +148,19 @@ impl<A: Debug, B: Debug> Debug for Eithe
         match *self {
             Either::First(ref v) => v.fmt(f),
             Either::Second(ref v) => v.fmt(f),
         }
     }
 }
 
 /// <https://drafts.csswg.org/css-values-4/#custom-idents>
-#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct CustomIdent(pub Atom);
 
 impl CustomIdent {
     /// Parse an already-tokenizer identifier
     pub fn from_ident<'i>(
         location: SourceLocation,
         ident: &CowRcStr<'i>,
         excluding: &[&str],
@@ -184,17 +187,17 @@ impl ToCss for CustomIdent {
     where
         W: Write,
     {
         serialize_atom_identifier(&self.0, dest)
     }
 }
 
 /// <https://drafts.csswg.org/css-animations/#typedef-keyframes-name>
-#[derive(Clone, Debug, MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
+#[derive(Clone, Debug, MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToShmem)]
 pub enum KeyframesName {
     /// <custom-ident>
     Ident(CustomIdent),
     /// <string>
     QuotedString(Atom),
 }
 
 impl KeyframesName {
--- a/servo/components/style/values/specified/align.rs
+++ b/servo/components/style/values/specified/align.rs
@@ -11,17 +11,17 @@ use crate::parser::{Parse, ParserContext
 use cssparser::Parser;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, KeywordsCollectFn, ParseError, SpecifiedValueInfo, ToCss};
 
 bitflags! {
     /// Constants shared by multiple CSS Box Alignment properties
     ///
     /// These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
-    #[derive(MallocSizeOf, ToComputedValue)]
+    #[derive(MallocSizeOf, ToComputedValue, ToShmem)]
     pub struct AlignFlags: u8 {
         // Enumeration stored in the lower 5 bits:
         /// 'auto'
         const AUTO =            structs::NS_STYLE_ALIGN_AUTO as u8;
         /// 'normal'
         const NORMAL =          structs::NS_STYLE_ALIGN_NORMAL as u8;
         /// 'start'
         const START =           structs::NS_STYLE_ALIGN_START as u8;
@@ -129,17 +129,17 @@ pub enum AxisDirection {
     Block,
     /// Inline direction.
     Inline,
 }
 
 /// Shared value for the `align-content` and `justify-content` properties.
 ///
 /// <https://drafts.csswg.org/css-align/#content-distribution>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 pub struct ContentDistribution {
     primary: AlignFlags,
     // FIXME(https://github.com/w3c/csswg-drafts/issues/1002): This will need to
     // accept fallback alignment, eventually.
 }
 
 impl ContentDistribution {
@@ -242,17 +242,17 @@ impl ContentDistribution {
             f(&["left", "right"]);
         }
     }
 }
 
 /// Value for the `align-content` property.
 ///
 /// <https://drafts.csswg.org/css-align/#propdef-align-content>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct AlignContent(pub ContentDistribution);
 
 impl Parse for AlignContent {
     fn parse<'i, 't>(
         _: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         // NOTE Please also update `impl SpecifiedValueInfo` below when
@@ -282,17 +282,17 @@ impl From<AlignContent> for u16 {
     fn from(v: AlignContent) -> u16 {
         v.0.as_bits()
     }
 }
 
 /// Value for the `justify-content` property.
 ///
 /// <https://drafts.csswg.org/css-align/#propdef-justify-content>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct JustifyContent(pub ContentDistribution);
 
 impl Parse for JustifyContent {
     fn parse<'i, 't>(
         _: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         // NOTE Please also update `impl SpecifiedValueInfo` below when
@@ -320,17 +320,17 @@ impl From<u16> for JustifyContent {
 #[cfg(feature = "gecko")]
 impl From<JustifyContent> for u16 {
     fn from(v: JustifyContent) -> u16 {
         v.0.as_bits()
     }
 }
 
 /// <https://drafts.csswg.org/css-align/#self-alignment>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct SelfAlignment(pub AlignFlags);
 
 impl SelfAlignment {
     /// The initial value 'auto'
     #[inline]
     pub fn auto() -> Self {
         SelfAlignment(AlignFlags::AUTO)
     }
@@ -380,17 +380,17 @@ impl SelfAlignment {
         list_overflow_position_keywords(f);
         list_self_position_keywords(f, axis);
     }
 }
 
 /// The specified value of the align-self property.
 ///
 /// <https://drafts.csswg.org/css-align/#propdef-align-self>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct AlignSelf(pub SelfAlignment);
 
 impl Parse for AlignSelf {
     fn parse<'i, 't>(
         _: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         // NOTE Please also update `impl SpecifiedValueInfo` below when
@@ -418,17 +418,17 @@ impl From<AlignSelf> for u8 {
     fn from(align: AlignSelf) -> u8 {
         (align.0).0.bits()
     }
 }
 
 /// The specified value of the justify-self property.
 ///
 /// <https://drafts.csswg.org/css-align/#propdef-justify-self>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct JustifySelf(pub SelfAlignment);
 
 impl Parse for JustifySelf {
     fn parse<'i, 't>(
         _: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         // NOTE Please also update `impl SpecifiedValueInfo` below when
@@ -456,17 +456,17 @@ impl From<JustifySelf> for u8 {
     fn from(justify: JustifySelf) -> u8 {
         (justify.0).0.bits()
     }
 }
 
 /// Value of the `align-items` property
 ///
 /// <https://drafts.csswg.org/css-align/#propdef-align-items>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
 pub struct AlignItems(pub AlignFlags);
 
 impl AlignItems {
     /// The initial value 'normal'
     #[inline]
     pub fn normal() -> Self {
         AlignItems(AlignFlags::NORMAL)
     }
@@ -507,17 +507,17 @@ impl SpecifiedValueInfo for AlignItems {
         list_overflow_position_keywords(f);
         list_self_position_keywords(f, AxisDirection::Block);
     }
 }
 
 /// Value of the `justify-items` property
 ///
 /// <https://drafts.csswg.org/css-align/#justify-items-property>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub struct JustifyItems(pub AlignFlags);
 
 impl JustifyItems {
     /// The initial value 'legacy'
     #[inline]
     pub fn legacy() -> Self {
         JustifyItems(AlignFlags::LEGACY)
     }
--- a/servo/components/style/values/specified/angle.rs
+++ b/servo/components/style/values/specified/angle.rs
@@ -12,17 +12,17 @@ use crate::values::CSSFloat;
 use crate::Zero;
 use cssparser::{Parser, Token};
 use std::f32::consts::PI;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
 
 /// A specified angle dimension.
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToCss, ToShmem)]
 pub enum AngleDimension {
     /// An angle with degree unit.
     #[css(dimension)]
     Deg(CSSFloat),
     /// An angle with gradian unit.
     #[css(dimension)]
     Grad(CSSFloat),
     /// An angle with radian unit.
@@ -63,17 +63,17 @@ impl AngleDimension {
             AngleDimension::Grad(gradians) => gradians * DEG_PER_GRAD,
         }
     }
 }
 
 /// A specified Angle value, which is just the angle dimension, plus whether it
 /// was specified as `calc()` or not.
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub struct Angle {
     value: AngleDimension,
     was_calc: bool,
 }
 
 impl Zero for Angle {
     fn zero() -> Self {
         Self {
--- a/servo/components/style/values/specified/background.rs
+++ b/servo/components/style/values/specified/background.rs
@@ -42,32 +42,33 @@ impl Parse for BackgroundSize {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 #[value_info(other_values = "repeat-x,repeat-y")]
 pub enum BackgroundRepeatKeyword {
     Repeat,
     Space,
     Round,
     NoRepeat,
 }
 
 /// The value of the `background-repeat` property, with `repeat-x` / `repeat-y`
 /// represented as the combination of `no-repeat` and `repeat` in the opposite
 /// axes.
 ///
 /// https://drafts.csswg.org/css-backgrounds/#the-background-repeat
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem)]
 pub struct BackgroundRepeat(pub BackgroundRepeatKeyword, pub BackgroundRepeatKeyword);
 
 impl BackgroundRepeat {
     /// Returns the `repeat repeat` value.
     pub fn repeat() -> Self {
         BackgroundRepeat(
             BackgroundRepeatKeyword::Repeat,
             BackgroundRepeatKeyword::Repeat,
--- a/servo/components/style/values/specified/border.rs
+++ b/servo/components/style/values/specified/border.rs
@@ -35,16 +35,17 @@ use style_traits::{CssWriter, ParseError
     MallocSizeOf,
     Ord,
     Parse,
     PartialEq,
     PartialOrd,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum BorderStyle {
     Hidden,
     None,
     Inset,
     Groove,
     Outset,
@@ -59,17 +60,17 @@ impl BorderStyle {
     /// Whether this border style is either none or hidden.
     #[inline]
     pub fn none_or_hidden(&self) -> bool {
         matches!(*self, BorderStyle::None | BorderStyle::Hidden)
     }
 }
 
 /// A specified value for a single side of the `border-width` property.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum BorderSideWidth {
     /// `thin`
     Thin,
     /// `medium`
     Medium,
     /// `thick`
     Thick,
     /// `<length>`
@@ -244,28 +245,32 @@ impl Parse for BorderSpacing {
         })
         .map(GenericBorderSpacing)
     }
 }
 
 /// A single border-image-repeat keyword.
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
+)]
 pub enum BorderImageRepeatKeyword {
     Stretch,
     Repeat,
     Round,
     Space,
 }
 
 /// The specified value for the `border-image-repeat` property.
 ///
 /// https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct BorderImageRepeat(pub BorderImageRepeatKeyword, pub BorderImageRepeatKeyword);
 
 impl ToCss for BorderImageRepeat {
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: Write,
     {
         self.0.to_css(dest)?;
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -56,16 +56,17 @@ fn moz_box_display_values_enabled(contex
     FromPrimitive,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[repr(u8)]
 pub enum Display {
     None = 0,
     Block,
     #[cfg(feature = "gecko")]
     FlowRoot,
@@ -319,17 +320,19 @@ impl AnimationIterationCount {
     /// Returns the value `1.0`.
     #[inline]
     pub fn one() -> Self {
         GenericAnimationIterationCount::Number(Number::new(1.0))
     }
 }
 
 /// A value for the `animation-name` property.
-#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 #[value_info(other_values = "none")]
 pub struct AnimationName(pub Option<KeyframesName>);
 
 impl AnimationName {
     /// Get the name of the animation as an `Atom`.
     pub fn as_atom(&self) -> Option<&Atom> {
         self.0.as_ref().map(|n| n.as_atom())
     }
@@ -374,16 +377,17 @@ impl Parse for AnimationName {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum ScrollSnapType {
     None,
     Mandatory,
     Proximity,
 }
 
@@ -397,28 +401,31 @@ pub enum ScrollSnapType {
     FromPrimitive,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum ScrollSnapAlignKeyword {
     None,
     Start,
     End,
     Center,
 }
 
 /// https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-align
 #[allow(missing_docs)]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 #[repr(C)]
 pub struct ScrollSnapAlign {
     block: ScrollSnapAlignKeyword,
     inline: ScrollSnapAlignKeyword,
 }
 
 impl ScrollSnapAlign {
     /// Returns `none`.
@@ -465,16 +472,17 @@ impl ToCss for ScrollSnapAlign {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum OverscrollBehavior {
     Auto,
     Contain,
     None,
 }
 
@@ -486,16 +494,17 @@ pub enum OverscrollBehavior {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum OverflowAnchor {
     Auto,
     None,
 }
 
 #[allow(missing_docs)]
@@ -506,24 +515,27 @@ pub enum OverflowAnchor {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum OverflowClipBox {
     PaddingBox,
     ContentBox,
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 /// Provides a rendering hint to the user agent,
 /// stating what kinds of changes the author expects
 /// to perform on the element
 ///
 /// <https://drafts.csswg.org/css-will-change/#will-change>
 pub enum WillChange {
     /// Expresses no particular intent
     Auto,
@@ -545,17 +557,17 @@ impl WillChange {
     /// Get default value of `will-change` as `auto`
     pub fn auto() -> WillChange {
         WillChange::Auto
     }
 }
 
 bitflags! {
     /// The change bits that we care about.
-    #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
+    #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToShmem)]
     #[repr(C)]
     pub struct WillChangeBits: u8 {
         /// Whether the stacking context will change.
         const STACKING_CONTEXT = 1 << 0;
         /// Whether `transform` will change.
         const TRANSFORM = 1 << 1;
         /// Whether `scroll-position` will change.
         const SCROLL = 1 << 2;
@@ -641,17 +653,18 @@ impl Parse for WillChange {
             bits,
         })
     }
 }
 
 bitflags! {
     /// Values for the `touch-action` property.
     #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-    #[derive(SpecifiedValueInfo, ToComputedValue)]
+    #[derive(SpecifiedValueInfo, ToComputedValue, ToShmem)]
+    /// These constants match Gecko's `NS_STYLE_TOUCH_ACTION_*` constants.
     #[value_info(other_values = "auto,none,manipulation,pan-x,pan-y")]
     #[repr(C)]
     pub struct TouchAction: u8 {
         /// `none` variant
         const NONE = 1 << 0;
         /// `auto` variant
         const AUTO = 1 << 1;
         /// `pan-x` variant
@@ -713,17 +726,17 @@ impl Parse for TouchAction {
                     Ok(TouchAction::PAN_Y)
                 }
             },
         }
     }
 }
 
 bitflags! {
-    #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
+    #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToShmem)]
     #[value_info(other_values = "none,strict,content,size,layout,paint")]
     #[repr(C)]
     /// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
     pub struct Contain: u8 {
         /// `none` variant, just for convenience.
         const NONE = 0;
         /// 'size' variant, turns on size containment
         const SIZE = 1 << 0;
@@ -815,17 +828,17 @@ impl Parse for Contain {
     }
 }
 
 /// A specified value for the `perspective` property.
 pub type Perspective = GenericPerspective<NonNegativeLength>;
 
 /// A given transition property, that is either `All`, a longhand or shorthand
 /// property, or an unsupported or custom property.
-#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToShmem)]
 pub enum TransitionProperty {
     /// A shorthand.
     Shorthand(ShorthandId),
     /// A longhand transitionable property.
     Longhand(LonghandId),
     /// A custom property.
     Custom(CustomPropertyName),
     /// Unrecognized property which could be any non-transitionable, custom property, or
@@ -910,49 +923,79 @@ impl TransitionProperty {
             TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => return Err(()),
         })
     }
 }
 
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[derive(
-    Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    Eq,
+    Hash,
+    MallocSizeOf,
+    Parse,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToCss,
+    ToShmem,
 )]
 /// https://drafts.csswg.org/css-box/#propdef-float
 pub enum Float {
     Left,
     Right,
     None,
     // https://drafts.csswg.org/css-logical-props/#float-clear
     InlineStart,
     InlineEnd,
 }
 
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[derive(
-    Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    Eq,
+    Hash,
+    MallocSizeOf,
+    Parse,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToCss,
+    ToShmem,
 )]
 /// https://drafts.csswg.org/css-box/#propdef-clear
 pub enum Clear {
     None,
     Left,
     Right,
     Both,
     // https://drafts.csswg.org/css-logical-props/#float-clear
     InlineStart,
     InlineEnd,
 }
 
 /// https://drafts.csswg.org/css-ui/#propdef-resize
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[derive(
-    Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    Eq,
+    Hash,
+    MallocSizeOf,
+    Parse,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToCss,
+    ToShmem,
 )]
 pub enum Resize {
     None,
     Both,
     Horizontal,
     Vertical,
     // https://drafts.csswg.org/css-logical-1/#resize
     Inline,
@@ -970,16 +1013,17 @@ pub enum Resize {
     Eq,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToCss,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum Appearance {
     /// No appearance at all.
     None,
     /// A typical dialog button.
     Button,
     /// Various arrows that go in buttons
@@ -1321,16 +1365,17 @@ pub enum Appearance {
     Eq,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToCss,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum BreakBetween {
     Always,
     Auto,
     Page,
     Avoid,
     Left,
@@ -1392,16 +1437,17 @@ impl BreakBetween {
     Eq,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToCss,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum BreakWithin {
     Auto,
     Avoid,
 }
 
 /// The value for the `overflow-x` / `overflow-y` properties.
@@ -1413,16 +1459,17 @@ pub enum BreakWithin {
     Eq,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToCss,
     ToComputedValue,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum Overflow {
     Visible,
     Hidden,
     Scroll,
     Auto,
     #[cfg(feature = "gecko")]
--- a/servo/components/style/values/specified/calc.rs
+++ b/servo/components/style/values/specified/calc.rs
@@ -60,17 +60,17 @@ pub enum CalcUnit {
 }
 
 /// A struct to hold a simplified `<length>` or `<percentage>` expression.
 ///
 /// In some cases, e.g. DOMMatrix, we support calc(), but reject all the
 /// relative lengths, and to_computed_pixel_length_without_context() handles
 /// this case. Therefore, if you want to add a new field, please make sure this
 /// function work properly.
-#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq, ToShmem)]
 #[allow(missing_docs)]
 pub struct CalcLengthPercentage {
     pub clamping_mode: AllowedNumericType,
     pub absolute: Option<AbsoluteLength>,
     pub vw: Option<CSSFloat>,
     pub vh: Option<CSSFloat>,
     pub vmin: Option<CSSFloat>,
     pub vmax: Option<CSSFloat>,
--- a/servo/components/style/values/specified/color.rs
+++ b/servo/components/style/values/specified/color.rs
@@ -17,17 +17,17 @@ use cssparser::{AngleOrNumber, Color as 
 use cssparser::{BasicParseErrorKind, NumberOrPercentage, ParseErrorKind};
 use itoa;
 use std::fmt::{self, Write};
 use std::io::Write as IoWrite;
 use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError, StyleParseErrorKind};
 use style_traits::{SpecifiedValueInfo, ToCss, ValueParseErrorKind};
 
 /// Specified color value
-#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub enum Color {
     /// The 'currentColor' keyword
     CurrentColor,
     /// A specific RGBA color
     Numeric {
         /// Parsed RGBA color
         parsed: RGBA,
         /// Authored representation
@@ -44,17 +44,17 @@ pub enum Color {
     Special(gecko::SpecialColorKeyword),
     /// Quirksmode-only rule for inheriting color from the body
     #[cfg(feature = "gecko")]
     InheritFromBodyQuirk,
 }
 
 #[cfg(feature = "gecko")]
 mod gecko {
-    #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss)]
+    #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)]
     pub enum SpecialColorKeyword {
         MozDefaultColor,
         MozDefaultBackgroundColor,
         MozHyperlinktext,
         MozActivehyperlinktext,
         MozVisitedhyperlinktext,
     }
 }
@@ -390,17 +390,17 @@ impl ToComputedValue for Color {
             GenericColor::Foreground => Color::currentcolor(),
             GenericColor::Complex(..) => Color::Complex(*computed),
         }
     }
 }
 
 /// Specified color value, but resolved to just RGBA for computed value
 /// with value from color property at the same context.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub struct RGBAColor(pub Color);
 
 impl Parse for RGBAColor {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         Color::parse(context, input).map(RGBAColor)
@@ -438,17 +438,17 @@ impl SpecifiedValueInfo for Color {
         // keep it consistent with the old system for now.
         f(&["rgb", "rgba", "hsl", "hsla", "currentColor", "transparent"]);
     }
 }
 
 /// Specified value for the "color" property, which resolves the `currentcolor`
 /// keyword to the parent color instead of self's color.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub struct ColorPropertyValue(pub Color);
 
 impl ToComputedValue for ColorPropertyValue {
     type ComputedValue = RGBA;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> RGBA {
         self.0
--- a/servo/components/style/values/specified/effects.rs
+++ b/servo/components/style/values/specified/effects.rs
@@ -32,17 +32,17 @@ pub type BoxShadow =
 #[cfg(feature = "gecko")]
 pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow, SpecifiedUrl>;
 
 /// A specified value for a single `filter`.
 #[cfg(not(feature = "gecko"))]
 pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible, Impossible>;
 
 /// A value for the `<factor>` parts in `Filter`.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub struct Factor(NumberOrPercentage);
 
 impl Factor {
     /// Parse this factor but clamp to one if the value is over 100%.
     #[inline]
     pub fn parse_with_clamping_to_one<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -76,17 +76,17 @@ pub const MIN_FONT_WEIGHT: f32 = 1.;
 /// The maximum font-weight value per:
 ///
 /// https://drafts.csswg.org/css-fonts-4/#font-weight-numeric-values
 pub const MAX_FONT_WEIGHT: f32 = 1000.;
 
 /// A specified font-weight value.
 ///
 /// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight
-#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum FontWeight {
     /// `<font-weight-absolute>`
     Absolute(AbsoluteFontWeight),
     /// Bolder variant
     Bolder,
     /// Lighter variant
     Lighter,
     /// System font variant.
@@ -138,17 +138,17 @@ impl ToComputedValue for FontWeight {
             &computed.0,
         )))
     }
 }
 
 /// An absolute font-weight value for a @font-face rule.
 ///
 /// https://drafts.csswg.org/css-fonts-4/#font-weight-absolute-values
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum AbsoluteFontWeight {
     /// A `<number>`, with the additional constraints specified in:
     ///
     ///   https://drafts.csswg.org/css-fonts-4/#font-weight-numeric-values
     Weight(Number),
     /// Normal font weight. Same as 400.
     Normal,
     /// Bold font weight. Same as 700.
@@ -314,17 +314,17 @@ impl SpecifiedFontStyle {
         Angle::from_degrees(
             DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES,
             /* was_calc = */ false,
         )
     }
 }
 
 /// The specified value of the `font-style` property.
-#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 #[allow(missing_docs)]
 pub enum FontStyle {
     Specified(SpecifiedFontStyle),
     #[css(skip)]
     System(SystemFont),
 }
 
 impl FontStyle {
@@ -353,27 +353,29 @@ impl ToComputedValue for FontStyle {
 }
 
 /// A value for the `font-stretch` property.
 ///
 /// https://drafts.csswg.org/css-fonts-4/#font-stretch-prop
 ///
 /// TODO(emilio): We could derive Parse if we had NonNegativePercentage.
 #[allow(missing_docs)]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 #[repr(u8)]
 pub enum FontStretch {
     Stretch(Percentage),
     Keyword(FontStretchKeyword),
     #[css(skip)]
     System(SystemFont),
 }
 
 /// A keyword value for `font-stretch`.
-#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
+)]
 #[allow(missing_docs)]
 pub enum FontStretchKeyword {
     Normal,
     Condensed,
     UltraCondensed,
     ExtraCondensed,
     SemiCondensed,
     SemiExpanded,
@@ -476,17 +478,17 @@ impl ToComputedValue for FontStretch {
         }
     }
 
     fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         FontStretch::Stretch(Percentage::from_computed_value(&(computed.0).0))
     }
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// A specified font-size value
 pub enum FontSize {
     /// A length; e.g. 10px.
     Length(LengthPercentage),
     /// A keyword value, along with a ratio and absolute offset.
     /// The ratio in any specified keyword value
     /// will be 1 (with offset 0), but we cascade keywordness even
     /// after font-relative (percent and em) values
@@ -508,17 +510,17 @@ pub enum FontSize {
 
 impl From<LengthPercentage> for FontSize {
     fn from(other: LengthPercentage) -> Self {
         FontSize::Length(other)
     }
 }
 
 /// Specifies a prioritized list of font family names or generic family names.
-#[derive(Clone, Debug, Eq, Hash, PartialEq, ToCss)]
+#[derive(Clone, Debug, Eq, Hash, PartialEq, ToCss, ToShmem)]
 pub enum FontFamily {
     /// List of `font-family`
     #[css(comma)]
     Values(#[css(iterable)] FontFamilyList),
     /// System font
     #[css(skip)]
     System(SystemFont),
 }
@@ -607,17 +609,17 @@ impl Parse for FamilyName {
             Ok(SingleFontFamily::Generic(_)) => {
                 Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
             },
             Err(e) => Err(e),
         }
     }
 }
 
-#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Preserve the readability of text when font fallback occurs
 pub enum FontSizeAdjust {
     /// None variant
     None,
     /// Number variant
     Number(NonNegativeNumber),
     /// system font
     #[css(skip)]
@@ -997,17 +999,17 @@ bitflags! {
         const SWASH = 0x10;
         /// Ornaments glyphs
         const ORNAMENTS = 0x20;
         /// Annotation forms
         const ANNOTATION = 0x40;
     }
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Set of variant alternates
 pub enum VariantAlternates {
     /// Enables display of stylistic alternates
     #[css(function)]
     Stylistic(CustomIdent),
     /// Enables display with stylistic sets
     #[css(comma, function)]
     Styleset(#[css(iterable)] Box<[CustomIdent]>),
@@ -1022,17 +1024,17 @@ pub enum VariantAlternates {
     Ornaments(CustomIdent),
     /// Enables display of alternate annotation forms
     #[css(function)]
     Annotation(CustomIdent),
     /// Enables display of historical forms
     HistoricalForms,
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// List of Variant Alternates
 pub struct VariantAlternatesList(
     #[css(if_empty = "normal", iterable)] pub Box<[VariantAlternates]>,
 );
 
 impl VariantAlternatesList {
     /// Returns the length of all variant alternates.
     pub fn len(&self) -> usize {
@@ -1043,17 +1045,17 @@ impl VariantAlternatesList {
             VariantAlternates::Annotation(_) => acc + 1,
             VariantAlternates::Styleset(ref slice) |
             VariantAlternates::CharacterVariant(ref slice) => acc + slice.len(),
             _ => acc,
         })
     }
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Control over the selection of these alternate glyphs
 pub enum FontVariantAlternates {
     /// Use alternative glyph from value
     Value(VariantAlternatesList),
     /// Use system font glyph
     #[css(skip)]
     System(SystemFont),
 }
@@ -1190,17 +1192,17 @@ impl Parse for FontVariantAlternates {
 macro_rules! impl_variant_east_asian {
     {
         $(
             $(#[$($meta:tt)+])*
             $ident:ident / $css:expr => $gecko:ident = $value:expr,
         )+
     } => {
         bitflags! {
-            #[derive(MallocSizeOf)]
+            #[derive(MallocSizeOf, ToShmem)]
             /// Vairants for east asian variant
             pub struct VariantEastAsian: u16 {
                 /// None of the features
                 const NORMAL = 0;
                 $(
                     $(#[$($meta)+])*
                     const $ident = $value;
                 )+
@@ -1279,17 +1281,17 @@ impl VariantEastAsian {
         self.bits()
     }
 }
 
 #[cfg(feature = "gecko")]
 impl_gecko_keyword_conversions!(VariantEastAsian, u16);
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Allows control of glyph substitution and sizing in East Asian text.
 pub enum FontVariantEastAsian {
     /// Value variant with `variant-east-asian`
     Value(VariantEastAsian),
     /// System font variant
     #[css(skip)]
     System(SystemFont),
 }
@@ -1397,17 +1399,17 @@ impl Parse for FontVariantEastAsian {
 macro_rules! impl_variant_ligatures {
     {
         $(
             $(#[$($meta:tt)+])*
             $ident:ident / $css:expr => $gecko:ident = $value:expr,
         )+
     } => {
         bitflags! {
-            #[derive(MallocSizeOf)]
+            #[derive(MallocSizeOf, ToShmem)]
             /// Variants of ligatures
             pub struct VariantLigatures: u16 {
                 /// Specifies that common default features are enabled
                 const NORMAL = 0;
                 $(
                     $(#[$($meta)+])*
                     const $ident = $value;
                 )+
@@ -1490,17 +1492,17 @@ impl VariantLigatures {
         self.bits()
     }
 }
 
 #[cfg(feature = "gecko")]
 impl_gecko_keyword_conversions!(VariantLigatures, u16);
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Ligatures and contextual forms are ways of combining glyphs
 /// to produce more harmonized forms
 pub enum FontVariantLigatures {
     /// Value variant with `variant-ligatures`
     Value(VariantLigatures),
     /// System font variant
     #[css(skip)]
     System(SystemFont),
@@ -1619,17 +1621,17 @@ impl Parse for FontVariantLigatures {
 macro_rules! impl_variant_numeric {
     {
         $(
             $(#[$($meta:tt)+])*
             $ident:ident / $css:expr => $gecko:ident = $value:expr,
         )+
     } => {
         bitflags! {
-            #[derive(MallocSizeOf)]
+            #[derive(MallocSizeOf, ToShmem)]
             /// Vairants of numeric values
             pub struct VariantNumeric: u8 {
                 /// None of other variants are enabled.
                 const NORMAL = 0;
                 $(
                     $(#[$($meta)+])*
                     const $ident = $value;
                 )+
@@ -1706,17 +1708,17 @@ impl VariantNumeric {
         self.bits()
     }
 }
 
 #[cfg(feature = "gecko")]
 impl_gecko_keyword_conversions!(VariantNumeric, u8);
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Specifies control over numerical forms.
 pub enum FontVariantNumeric {
     /// Value variant with `variant-numeric`
     Value(VariantNumeric),
     /// System font
     #[css(skip)]
     System(SystemFont),
 }
@@ -1815,17 +1817,17 @@ impl Parse for FontVariantNumeric {
     }
 }
 
 /// This property provides low-level control over OpenType or TrueType font features.
 pub type SpecifiedFontFeatureSettings = FontSettings<FeatureTagValue<Integer>>;
 
 /// Define initial settings that apply when the font defined by an @font-face
 /// rule is rendered.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum FontFeatureSettings {
     /// Value of `FontSettings`
     Value(SpecifiedFontFeatureSettings),
     /// System font
     #[css(skip)]
     System(SystemFont),
 }
 
@@ -1859,17 +1861,19 @@ impl Parse for FontFeatureSettings {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<FontFeatureSettings, ParseError<'i>> {
         SpecifiedFontFeatureSettings::parse(context, input).map(FontFeatureSettings::Value)
     }
 }
 
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 /// Whether user agents are allowed to synthesize bold or oblique font faces
 /// when a font family lacks bold or italic faces
 pub struct FontSynthesis {
     /// If a `font-weight` is requested that the font family does not contain,
     /// the user agent may synthesize the requested weight from the weights
     /// that do exist in the font family.
     #[css(represents_keyword)]
     pub weight: bool,
@@ -1959,17 +1963,17 @@ impl From<FontSynthesis> for u8 {
         }
         if v.style {
             bits |= structs::NS_FONT_SYNTHESIS_STYLE as u8;
         }
         bits
     }
 }
 
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Allows authors to explicitly specify the language system of the font,
 /// overriding the language system implied by the content language
 pub enum FontLanguageOverride {
     /// When rendering with OpenType fonts,
     /// the content language of the element is
     /// used to infer the OpenType language system
     Normal,
     /// Single three-letter case-sensitive OpenType language system tag,
@@ -2063,17 +2067,17 @@ impl Parse for FontLanguageOverride {
 }
 
 /// This property provides low-level control over OpenType or TrueType font
 /// variations.
 pub type SpecifiedFontVariationSettings = FontSettings<VariationValue<Number>>;
 
 /// Define initial settings that apply when the font defined by an @font-face
 /// rule is rendered.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum FontVariationSettings {
     /// Value of `FontSettings`
     Value(SpecifiedFontVariationSettings),
     /// System font
     #[css(skip)]
     System(SystemFont),
 }
 
@@ -2150,17 +2154,25 @@ impl Parse for VariationValue<Number> {
     ) -> Result<Self, ParseError<'i>> {
         let tag = FontTag::parse(context, input)?;
         let value = Number::parse(context, input)?;
         Ok(Self { tag, value })
     }
 }
 
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 /// text-zoom. Enable if true, disable if false
 pub struct XTextZoom(#[css(skip)] pub bool);
 
 impl Parse for XTextZoom {
     fn parse<'i, 't>(
         _: &ParserContext,
         input: &mut Parser<'i, 't>,
@@ -2168,17 +2180,19 @@ impl Parse for XTextZoom {
         debug_assert!(
             false,
             "Should be set directly by presentation attributes only."
         );
         Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
     }
 }
 
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 /// Internal property that reflects the lang attribute
 pub struct XLang(#[css(skip)] pub Atom);
 
 impl XLang {
     #[inline]
     /// Get default value for `-x-lang`
     pub fn get_initial_value() -> XLang {
         XLang(atom!(""))
@@ -2194,17 +2208,17 @@ impl Parse for XLang {
             false,
             "Should be set directly by presentation attributes only."
         );
         Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
     }
 }
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Specifies the minimum font size allowed due to changes in scriptlevel.
 /// Ref: https://wiki.mozilla.org/MathML:mstyle
 pub struct MozScriptMinSize(pub NoCalcLength);
 
 impl MozScriptMinSize {
     #[inline]
     /// Calculate initial value of -moz-script-min-size.
     pub fn get_initial_value() -> Length {
@@ -2221,17 +2235,17 @@ impl Parse for MozScriptMinSize {
             false,
             "Should be set directly by presentation attributes only."
         );
         Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
     }
 }
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// Changes the scriptlevel in effect for the children.
 /// Ref: https://wiki.mozilla.org/MathML:mstyle
 ///
 /// The main effect of scriptlevel is to control the font size.
 /// https://www.w3.org/TR/MathML3/chapter3.html#presm.scriptlevel
 pub enum MozScriptLevel {
     /// Change `font-size` relatively.
     Relative(i32),
@@ -2256,17 +2270,17 @@ impl Parse for MozScriptLevel {
             return Ok(MozScriptLevel::Relative(i));
         }
         input.expect_ident_matching("auto")?;
         Ok(MozScriptLevel::Auto)
     }
 }
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem)]
 /// Specifies the multiplier to be used to adjust font size
 /// due to changes in scriptlevel.
 ///
 /// Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.mstyle.attrs
 pub struct MozScriptSizeMultiplier(pub f32);
 
 impl MozScriptSizeMultiplier {
     #[inline]
--- a/servo/components/style/values/specified/image.rs
+++ b/servo/components/style/values/specified/image.rs
@@ -91,17 +91,17 @@ pub type GradientKind =
     generic::GradientKind<LineDirection, Length, LengthPercentage, Position, Angle>;
 
 /// A specified gradient kind.
 #[cfg(feature = "gecko")]
 pub type GradientKind =
     generic::GradientKind<LineDirection, Length, LengthPercentage, GradientPosition, Angle>;
 
 /// A specified gradient line direction.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub enum LineDirection {
     /// An angular direction.
     Angle(Angle),
     /// A horizontal direction.
     Horizontal(X),
     /// A vertical direction.
     Vertical(Y),
     /// A direction towards a corner of a box.
@@ -110,17 +110,17 @@ pub enum LineDirection {
     /// `-moz-` prefixed linear gradient can contain both a position and an angle but it
     /// uses legacy syntax for position. That means we can't specify both keyword and
     /// length for each horizontal/vertical components.
     #[cfg(feature = "gecko")]
     MozPosition(Option<LegacyPosition>, Option<Angle>),
 }
 
 /// A binary enum to hold either Position or LegacyPosition.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 #[cfg(feature = "gecko")]
 pub enum GradientPosition {
     /// 1, 2, 3, 4-valued <position>.
     Modern(Position),
     /// 1, 2-valued <position>.
     Legacy(LegacyPosition),
 }
 
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -51,17 +51,17 @@ pub const AU_PER_PC: CSSFloat = AU_PER_P
 ///
 /// Converts app units to integer pixel values,
 /// rounding during the conversion
 pub fn au_to_int_px(au: f32) -> i32 {
     (au / AU_PER_PX).round() as i32
 }
 
 /// A font relative length.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub enum FontRelativeLength {
     /// A "em" value: https://drafts.csswg.org/css-values/#em
     #[css(dimension)]
     Em(CSSFloat),
     /// A "ex" value: https://drafts.csswg.org/css-values/#ex
     #[css(dimension)]
     Ex(CSSFloat),
     /// A "ch" value: https://drafts.csswg.org/css-values/#ch
@@ -231,17 +231,17 @@ impl FontRelativeLength {
             },
         }
     }
 }
 
 /// A viewport-relative length.
 ///
 /// <https://drafts.csswg.org/css-values/#viewport-relative-lengths>
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub enum ViewportPercentageLength {
     /// A vw unit: https://drafts.csswg.org/css-values/#vw
     #[css(dimension)]
     Vw(CSSFloat),
     /// A vh unit: https://drafts.csswg.org/css-values/#vh
     #[css(dimension)]
     Vh(CSSFloat),
     /// <https://drafts.csswg.org/css-values/#vmin>
@@ -280,17 +280,17 @@ impl ViewportPercentageLength {
         // See bug 989802. We truncate so that adding multiple viewport units
         // that add up to 100 does not overflow due to rounding differences
         let trunc_scaled = ((length.0 as f64) * factor as f64 / 100.).trunc();
         Au::from_f64_au(trunc_scaled).into()
     }
 }
 
 /// HTML5 "character width", as defined in HTML5 § 14.5.4.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub struct CharacterWidth(pub i32);
 
 impl CharacterWidth {
     /// Computes the given character width.
     pub fn to_computed_value(&self, reference_font_size: Au) -> CSSPixelLength {
         // This applies the *converting a character width to pixels* algorithm as specified
         // in HTML5 § 14.5.4.
         //
@@ -298,17 +298,17 @@ impl CharacterWidth {
         let average_advance = reference_font_size.scale_by(0.5);
         let max_advance = reference_font_size;
         let au = average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance;
         au.into()
     }
 }
 
 /// Represents an absolute length with its unit
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub enum AbsoluteLength {
     /// An absolute length in pixels (px)
     #[css(dimension)]
     Px(CSSFloat),
     /// An absolute length in inches (in)
     #[css(dimension)]
     In(CSSFloat),
     /// An absolute length in centimeters (cm)
@@ -404,17 +404,17 @@ impl Add<AbsoluteLength> for AbsoluteLen
             _ => AbsoluteLength::Px(self.to_px() + rhs.to_px()),
         }
     }
 }
 
 /// A `<length>` without taking `calc` expressions into account
 ///
 /// <https://drafts.csswg.org/css-values/#lengths>
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub enum NoCalcLength {
     /// An absolute length
     ///
     /// <https://drafts.csswg.org/css-values/#absolute-length>
     Absolute(AbsoluteLength),
 
     /// A font-relative length:
     ///
@@ -517,17 +517,17 @@ impl Zero for NoCalcLength {
         }
     }
 }
 
 /// An extension to `NoCalcLength` to parse `calc` expressions.
 /// This is commonly used for the `<length>` values.
 ///
 /// <https://drafts.csswg.org/css-values/#lengths>
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum Length {
     /// The internal length type that cannot parse `calc`
     NoCalc(NoCalcLength),
     /// A calc expression.
     ///
     /// <https://drafts.csswg.org/css-values/#calc-notation>
     Calc(Box<CalcLengthPercentage>),
 }
@@ -737,17 +737,17 @@ impl NonNegativeLength {
     }
 }
 
 /// A `<length-percentage>` value. This can be either a `<length>`, a
 /// `<percentage>`, or a combination of both via `calc()`.
 ///
 /// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
 #[allow(missing_docs)]
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum LengthPercentage {
     Length(NoCalcLength),
     Percentage(computed::Percentage),
     Calc(Box<CalcLengthPercentage>),
 }
 
 impl From<Length> for LengthPercentage {
     fn from(len: Length) -> LengthPercentage {
--- a/servo/components/style/values/specified/list.rs
+++ b/servo/components/style/values/specified/list.rs
@@ -10,17 +10,19 @@ use crate::values::generics::CounterStyl
 #[cfg(feature = "gecko")]
 use crate::values::CustomIdent;
 use cssparser::{Parser, Token};
 use servo_arc::Arc;
 use style_traits::{ParseError, StyleParseErrorKind};
 
 /// Specified and computed `list-style-type` property.
 #[cfg(feature = "gecko")]
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub enum ListStyleType {
     /// <counter-style> | none
     CounterStyle(CounterStyleOrNone),
     /// <string>
     String(String),
 }
 
 #[cfg(feature = "gecko")]
@@ -69,27 +71,31 @@ impl Parse for ListStyleType {
 
         Ok(ListStyleType::String(
             input.expect_string()?.as_ref().to_owned(),
         ))
     }
 }
 
 /// A quote pair.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct QuotePair {
     /// The opening quote.
     pub opening: Box<str>,
 
     /// The closing quote.
     pub closing: Box<str>,
 }
 
 /// Specified and computed `quotes` property.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct Quotes(
     #[css(iterable, if_empty = "none")]
     #[ignore_malloc_size_of = "Arc"]
     pub Arc<Box<[QuotePair]>>,
 );
 
 impl Parse for Quotes {
     fn parse<'i, 't>(
@@ -132,16 +138,17 @@ impl Parse for Quotes {
     Eq,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum MozListReversed {
     /// the initial value
     False,
     /// exclusively used for <ol reversed> in our html.css UA sheet
     True,
 }
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -154,17 +154,17 @@ fn parse_number_with_clamping_mode<'i, '
         value: result.min(f32::MAX).max(f32::MIN),
         calc_clamping_mode: Some(clamping_mode),
     })
 }
 
 /// A CSS `<number>` specified value.
 ///
 /// https://drafts.csswg.org/css-values-3/#number-value
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToShmem)]
 pub struct Number {
     /// The numeric value itself.
     value: CSSFloat,
     /// If this number came from a calc() expression, this tells how clamping
     /// should be done on the value.
     calc_clamping_mode: Option<AllowedNumericType>,
 }
 
@@ -341,17 +341,17 @@ impl Parse for GreaterThanOrEqualToOneNu
 }
 
 /// <number> | <percentage>
 ///
 /// Accepts only non-negative numbers.
 ///
 /// FIXME(emilio): Should probably use Either.
 #[allow(missing_docs)]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum NumberOrPercentage {
     Percentage(Percentage),
     Number(Number),
 }
 
 impl NumberOrPercentage {
     fn parse_with_clamping_mode<'i, 't>(
         context: &ParserContext,
@@ -401,17 +401,19 @@ impl Parse for NonNegativeNumberOrPercen
     ) -> Result<Self, ParseError<'i>> {
         Ok(NonNegative(NumberOrPercentage::parse_non_negative(
             context, input,
         )?))
     }
 }
 
 #[allow(missing_docs)]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss, ToShmem,
+)]
 pub struct Opacity(Number);
 
 impl Parse for Opacity {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         Number::parse(context, input).map(Opacity)
@@ -437,17 +439,17 @@ impl ToComputedValue for Opacity {
     fn from_computed_value(computed: &CSSFloat) -> Self {
         Opacity(Number::from_computed_value(computed))
     }
 }
 
 /// A specified `<integer>`, optionally coming from a `calc()` expression.
 ///
 /// <https://drafts.csswg.org/css-values/#integers>
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, ToShmem)]
 pub struct Integer {
     value: CSSInteger,
     was_calc: bool,
 }
 
 impl One for Integer {
     #[inline]
     fn one() -> Self {
@@ -701,17 +703,19 @@ impl AllowQuirks {
             AllowQuirks::Yes => quirks_mode == QuirksMode::Quirks,
         }
     }
 }
 
 /// An attr(...) rule
 ///
 /// `[namespace? `|`]? ident`
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 #[css(function)]
 pub struct Attr {
     /// Optional namespace prefix and URL.
     pub namespace: Option<(Prefix, Namespace)>,
     /// Attribute name
     pub attribute: Atom,
 }
 
--- a/servo/components/style/values/specified/motion.rs
+++ b/servo/components/style/values/specified/motion.rs
@@ -18,16 +18,17 @@ use style_traits::{ParseError, StylePars
     ComputeSquaredDistance,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum OffsetPath {
     // We could merge SVGPathData into ShapeSource, so we could reuse them. However,
     // we don't want to support other value for offset-path, so use SVGPathData only for now.
     /// Path value for path(<string>).
     #[css(function)]
     Path(SVGPathData),
     /// None value.
--- a/servo/components/style/values/specified/outline.rs
+++ b/servo/components/style/values/specified/outline.rs
@@ -17,16 +17,17 @@ use style_traits::ParseError;
     Eq,
     MallocSizeOf,
     Ord,
     PartialEq,
     PartialOrd,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(C, u8)]
 /// <https://drafts.csswg.org/css-ui/#propdef-outline-style>
 pub enum OutlineStyle {
     /// auto
     Auto,
     /// <border-style>
     BorderStyle(BorderStyle),
--- a/servo/components/style/values/specified/percentage.rs
+++ b/servo/components/style/values/specified/percentage.rs
@@ -10,17 +10,17 @@ use crate::values::computed::{Context, T
 use crate::values::specified::calc::CalcNode;
 use crate::values::{serialize_percentage, CSSFloat};
 use cssparser::{Parser, Token};
 use std::fmt::{self, Write};
 use style_traits::values::specified::AllowedNumericType;
 use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
 
 /// A percentage value.
-#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Default, MallocSizeOf, PartialEq, ToShmem)]
 pub struct Percentage {
     /// The percentage value as a float.
     ///
     /// [0 .. 100%] maps to [0.0 .. 1.0]
     value: CSSFloat,
     /// If this percentage came from a calc() expression, this tells how
     /// clamping should be done on the value.
     calc_clamping_mode: Option<AllowedNumericType>,
--- a/servo/components/style/values/specified/position.rs
+++ b/servo/components/style/values/specified/position.rs
@@ -30,17 +30,17 @@ pub type Position = GenericPosition<Hori
 
 /// The specified value of a horizontal position.
 pub type HorizontalPosition = PositionComponent<X>;
 
 /// The specified value of a vertical position.
 pub type VerticalPosition = PositionComponent<Y>;
 
 /// The specified value of a component of a CSS `<position>`.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum PositionComponent<S> {
     /// `center`
     Center,
     /// `<length-percentage>`
     Length(LengthPercentage),
     /// `<side> <length-percentage>?`
     Side(S, Option<LengthPercentage>),
 }
@@ -53,16 +53,17 @@ pub enum PositionComponent<S> {
     Eq,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 pub enum X {
     Left,
     Right,
 }
 
 /// A keyword for the Y direction.
@@ -73,16 +74,17 @@ pub enum X {
     Eq,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 pub enum Y {
     Top,
     Bottom,
 }
 
 impl Parse for Position {
@@ -429,30 +431,48 @@ impl ToCss for LegacyPosition {
     {
         self.horizontal.to_css(dest)?;
         dest.write_str(" ")?;
         self.vertical.to_css(dest)
     }
 }
 
 #[derive(
-    Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    Eq,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 /// Auto-placement algorithm Option
 pub enum AutoFlow {
     /// The auto-placement algorithm places items by filling each row in turn,
     /// adding new rows as necessary.
     Row,
     /// The auto-placement algorithm places items by filling each column in turn,
     /// adding new columns as necessary.
     Column,
 }
 
 #[derive(
-    Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    Eq,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 /// Controls how the auto-placement algorithm works
 /// specifying exactly how auto-placed items get flowed into the grid
 pub struct GridAutoFlow {
     /// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
     pub autoflow: AutoFlow,
     /// Specify use `dense` packing algorithm or not
     #[css(represents_keyword)]
@@ -543,17 +563,17 @@ impl From<GridAutoFlow> for u8 {
         if v.dense {
             result |= structs::NS_STYLE_GRID_AUTO_FLOW_DENSE as u8;
         }
         result
     }
 }
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem)]
 /// https://drafts.csswg.org/css-grid/#named-grid-area
 pub struct TemplateAreas {
     /// `named area` containing for each template area
     #[css(skip)]
     pub areas: Box<[NamedArea]>,
     /// The original CSS string value of each template area
     #[css(iterable)]
     pub strings: Box<[Box<str>]>,
@@ -649,32 +669,34 @@ impl Parse for TemplateAreas {
         }
 
         TemplateAreas::from_vec(strings)
             .map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
     }
 }
 
 /// Arc type for `Arc<TemplateAreas>`
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct TemplateAreasArc(#[ignore_malloc_size_of = "Arc"] pub Arc<TemplateAreas>);
 
 impl Parse for TemplateAreasArc {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         let parsed = TemplateAreas::parse(context, input)?;
 
         Ok(TemplateAreasArc(Arc::new(parsed)))
     }
 }
 
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo)]
+#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToShmem)]
 /// Not associated with any particular grid item, but can
 /// be referenced from the grid-placement properties.
 pub struct NamedArea {
     /// Name of the `named area`
     pub name: Box<str>,
     /// Rows of the `named area`
     pub rows: Range<u32>,
     /// Columns of the `named area`
--- a/servo/components/style/values/specified/resolution.rs
+++ b/servo/components/style/values/specified/resolution.rs
@@ -7,17 +7,17 @@
 //! https://drafts.csswg.org/css-values/#resolution
 
 use crate::parser::{Parse, ParserContext};
 use crate::values::CSSFloat;
 use cssparser::{Parser, Token};
 use style_traits::{ParseError, StyleParseErrorKind};
 
 /// A specified resolution.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub enum Resolution {
     /// Dots per inch.
     #[css(dimension)]
     Dpi(CSSFloat),
     /// An alias unit for dots per pixel.
     #[css(dimension)]
     X(CSSFloat),
     /// Dots per pixel.
--- a/servo/components/style/values/specified/svg.rs
+++ b/servo/components/style/values/specified/svg.rs
@@ -123,17 +123,19 @@ const PAINT_ORDER_MASK: u8 = 0b11;
 ///
 /// Each pair can be set to FILL, STROKE, or MARKERS
 /// Lowest significant bit pairs are highest priority.
 ///  `normal` is the empty bitfield. The three pairs are
 /// never zero in any case other than `normal`.
 ///
 /// Higher priority values, i.e. the values specified first,
 /// will be painted first (and may be covered by paintings of lower priority)
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct SVGPaintOrder(pub u8);
 
 impl SVGPaintOrder {
     /// Get default `paint-order` with `0`
     pub fn normal() -> Self {
         SVGPaintOrder(0)
     }
 
@@ -230,17 +232,19 @@ impl ToCss for SVGPaintOrder {
             self.order_at(pos).to_css(dest)?;
         }
         Ok(())
     }
 }
 
 /// Specified MozContextProperties value.
 /// Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToShmem,
+)]
 pub struct MozContextProperties(pub CustomIdent);
 
 impl Parse for MozContextProperties {
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<MozContextProperties, ParseError<'i>> {
         let location = input.current_source_location();
--- a/servo/components/style/values/specified/svg_path.rs
+++ b/servo/components/style/values/specified/svg_path.rs
@@ -14,17 +14,24 @@ use std::iter::{Cloned, Peekable};
 use std::slice;
 use style_traits::values::SequenceWriter;
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
 /// The SVG path data.
 ///
 /// https://www.w3.org/TR/SVG11/paths.html#PathData
 #[derive(
-    Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
+    Clone,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToAnimatedZero,
+    ToComputedValue,
+    ToShmem,
 )]
 pub struct SVGPathData(Box<[PathCommand]>);
 
 impl SVGPathData {
     /// Return SVGPathData by a slice of PathCommand.
     #[inline]
     pub fn new(cmd: Box<[PathCommand]>) -> Self {
         debug_assert!(!cmd.is_empty());
@@ -142,16 +149,17 @@ impl ComputeSquaredDistance for SVGPathD
     Clone,
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 #[repr(C, u8)]
 pub enum PathCommand {
     /// The unknown type.
     /// https://www.w3.org/TR/SVG/paths.html#__svg__SVGPathSeg__PATHSEG_UNKNOWN
     Unknown,
     /// The "moveto" command.
@@ -468,16 +476,17 @@ impl ToCss for PathCommand {
     Clone,
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum IsAbsolute {
     Yes,
     No,
 }
 
 impl IsAbsolute {
@@ -496,30 +505,31 @@ impl IsAbsolute {
     ComputeSquaredDistance,
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToCss,
+    ToShmem,
 )]
 #[repr(C)]
 pub struct CoordPair(CSSFloat, CSSFloat);
 
 impl CoordPair {
     /// Create a CoordPair.
     #[inline]
     pub fn new(x: CSSFloat, y: CSSFloat) -> Self {
         CoordPair(x, y)
     }
 }
 
 /// The EllipticalArc flag type.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)]
 #[repr(C)]
 pub struct ArcFlag(bool);
 
 impl ToCss for ArcFlag {
     #[inline]
     fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
     where
         W: fmt::Write,
--- a/servo/components/style/values/specified/table.rs
+++ b/servo/components/style/values/specified/table.rs
@@ -4,17 +4,25 @@
 
 //! Specified types for table properties.
 
 use crate::parser::{Parse, ParserContext};
 use cssparser::Parser;
 use style_traits::{ParseError, StyleParseErrorKind};
 
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 /// span. for `<col span>` pres attr
 pub struct XSpan(#[css(skip)] pub i32);
 
 impl Parse for XSpan {
     // never parse it, only set via presentation attribute
     fn parse<'i, 't>(
         _: &ParserContext,
--- a/servo/components/style/values/specified/text.rs
+++ b/servo/components/style/values/specified/text.rs
@@ -129,17 +129,17 @@ impl ToComputedValue for LineHeight {
             GenericLineHeight::Length(ref length) => {
                 GenericLineHeight::Length(NoCalcLength::from_computed_value(&length.0).into())
             },
         }
     }
 }
 
 /// A generic value for the `text-overflow` property.
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum TextOverflowSide {
     /// Clip inline content.
     Clip,
     /// Render ellipsis to represent clipped inline content.
     Ellipsis,
     /// Render a given string to represent clipped inline content.
     String(Box<str>),
 }
@@ -163,17 +163,17 @@ impl Parse for TextOverflowSide {
             Token::QuotedString(ref v) => Ok(TextOverflowSide::String(
                 v.as_ref().to_owned().into_boxed_str(),
             )),
             ref t => Err(location.new_unexpected_token_error(t.clone())),
         }
     }
 }
 
-#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 /// text-overflow. Specifies rendering when inline content overflows its line box edge.
 pub struct TextOverflow {
     /// First value. Applies to end line box edge if no second is supplied; line-left edge otherwise.
     pub first: TextOverflowSide,
     /// Second value. Applies to the line-right edge if supplied.
     pub second: Option<TextOverflowSide>,
 }
 
@@ -223,17 +223,17 @@ impl ToComputedValue for TextOverflow {
                 first: computed.first.clone(),
                 second: Some(computed.second.clone()),
             }
         }
     }
 }
 
 bitflags! {
-    #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
+    #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToShmem)]
     #[value_info(other_values = "none,underline,overline,line-through,blink")]
     #[repr(C)]
     /// Specified keyword values for the text-decoration-line property.
     pub struct TextDecorationLine: u8 {
         /// No text decoration line is specified.
         const NONE = 0;
         /// underline
         const UNDERLINE = 1 << 0;
@@ -360,16 +360,17 @@ impl TextDecorationLine {
     FromPrimitive,
     Hash,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 pub enum TextAlignKeyword {
     Start,
     End,
     Left,
     Right,
     Center,
@@ -388,17 +389,17 @@ pub enum TextAlignKeyword {
     ServoRight,
     #[css(skip)]
     #[cfg(feature = "gecko")]
     Char,
 }
 
 /// Specified value of text-align property.
 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Copy, Debug, Eq, Hash, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, Hash, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum TextAlign {
     /// Keyword value of text-align property.
     Keyword(TextAlignKeyword),
     /// `match-parent` value of text-align property. It has a different handling
     /// unlike other keywords.
     #[cfg(feature = "gecko")]
     MatchParent,
     /// `MozCenterOrInherit` value of text-align property. It cannot be parsed,
@@ -465,28 +466,28 @@ impl ToComputedValue for TextAlign {
 
     #[inline]
     fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         TextAlign::Keyword(*computed)
     }
 }
 
 /// Specified value of text-emphasis-style property.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum TextEmphasisStyle {
     /// <fill> <shape>
     Keyword(TextEmphasisKeywordValue),
     /// `none`
     None,
     /// String (will be used only first grapheme cluster) for the text-emphasis-style property
     String(String),
 }
 
 /// Keyword value for the text-emphasis-style property
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum TextEmphasisKeywordValue {
     /// <fill>
     Fill(TextEmphasisFillMode),
     /// <shape>
     Shape(TextEmphasisShapeKeyword),
     /// <fill> <shape>
     FillAndShape(TextEmphasisFillMode, TextEmphasisShapeKeyword),
 }
@@ -505,26 +506,30 @@ impl TextEmphasisKeywordValue {
             TextEmphasisKeywordValue::Shape(shape) |
             TextEmphasisKeywordValue::FillAndShape(_, shape) => Some(shape),
             _ => None,
         }
     }
 }
 
 /// Fill mode for the text-emphasis-style property
-#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
+)]
 pub enum TextEmphasisFillMode {
     /// `filled`
     Filled,
     /// `open`
     Open,
 }
 
 /// Shape keyword for the text-emphasis-style property
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(
+    Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
+)]
 pub enum TextEmphasisShapeKeyword {
     /// `dot`
     Dot,
     /// `circle`
     Circle,
     /// `double-circle`
     DoubleCircle,
     /// `triangle`
@@ -664,16 +669,17 @@ impl Parse for TextEmphasisStyle {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum TextEmphasisHorizontalWritingModeValue {
     /// Draw marks over the text in horizontal writing mode.
     Over,
     /// Draw marks under the text in horizontal writing mode.
     Under,
 }
 
@@ -684,27 +690,36 @@ pub enum TextEmphasisHorizontalWritingMo
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 pub enum TextEmphasisVerticalWritingModeValue {
     /// Draws marks to the right of the text in vertical writing mode.
     Right,
     /// Draw marks to the left of the text in vertical writing mode.
     Left,
 }
 
 /// Specified value of `text-emphasis-position` property.
 #[derive(
-    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+    Clone,
+    Copy,
+    Debug,
+    MallocSizeOf,
+    PartialEq,
+    SpecifiedValueInfo,
+    ToComputedValue,
+    ToCss,
+    ToShmem,
 )]
 pub struct TextEmphasisPosition(
     pub TextEmphasisHorizontalWritingModeValue,
     pub TextEmphasisVerticalWritingModeValue,
 );
 
 impl TextEmphasisPosition {
     #[inline]
@@ -795,16 +810,17 @@ impl From<TextEmphasisPosition> for u8 {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 pub enum WordBreak {
     Normal,
     BreakAll,
     KeepAll,
     /// The break-word value, needed for compat.
     ///
@@ -822,15 +838,16 @@ pub enum WordBreak {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[allow(missing_docs)]
 pub enum OverflowWrap {
     Normal,
     BreakWord,
     Anywhere,
 }
--- a/servo/components/style/values/specified/time.rs
+++ b/servo/components/style/values/specified/time.rs
@@ -10,25 +10,25 @@ use crate::values::computed::{Context, T
 use crate::values::specified::calc::CalcNode;
 use crate::values::CSSFloat;
 use cssparser::{Parser, Token};
 use std::fmt::{self, Write};
 use style_traits::values::specified::AllowedNumericType;
 use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss};
 
 /// A time value according to CSS-VALUES § 6.2.
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)]
 pub struct Time {
     seconds: CSSFloat,
     unit: TimeUnit,
     was_calc: bool,
 }
 
 /// A time unit.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
 pub enum TimeUnit {
     /// `s`
     Second,
     /// `ms`
     Millisecond,
 }
 
 impl Time {
--- a/servo/components/style/values/specified/transform.rs
+++ b/servo/components/style/values/specified/transform.rs
@@ -227,17 +227,17 @@ impl Parse for Transform {
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         Transform::parse_internal(context, input)
     }
 }
 
 /// The specified value of a component of a CSS `<transform-origin>`.
-#[derive(Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
 pub enum OriginComponent<S> {
     /// `center`
     Center,
     /// `<length-percentage>`
     Length(LengthPercentage),
     /// `<side>`
     Side(S),
 }
--- a/servo/components/style/values/specified/ui.rs
+++ b/servo/components/style/values/specified/ui.rs
@@ -51,17 +51,19 @@ impl Parse for CursorImage {
                 Ok(number) => Some((number, Number::parse(context, input)?)),
                 Err(_) => None,
             },
         })
     }
 }
 
 /// Specified value of `-moz-force-broken-image-icon`
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
+#[derive(
+    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
 pub struct MozForceBrokenImageIcon(pub bool);
 
 impl MozForceBrokenImageIcon {
     /// Return initial value of -moz-force-broken-image-icon which is false.
     #[inline]
     pub fn false_value() -> MozForceBrokenImageIcon {
         MozForceBrokenImageIcon(false)
     }
@@ -134,16 +136,17 @@ impl Parse for ScrollbarColor {
     Debug,
     Eq,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum UserSelect {
     Auto,
     Text,
     #[parse(aliases = "-moz-none")]
     None,
     /// Force selection of all children.
@@ -161,16 +164,17 @@ pub enum UserSelect {
     Eq,
     FromPrimitive,
     MallocSizeOf,
     Parse,
     PartialEq,
     SpecifiedValueInfo,
     ToComputedValue,
     ToCss,
+    ToShmem,
 )]
 #[repr(u8)]
 pub enum CursorKind {
     None,
     Default,
     Pointer,
     ContextMenu,
     Help,
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -21,8 +21,10 @@ euclid = "0.19"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = "0.1"
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true}
 webrender_api = {git = "https://github.com/servo/webrender", optional = true}
 servo_atoms = {path = "../atoms", optional = true}
 servo_arc = { path = "../servo_arc" }
 servo_url = { path = "../url", optional = true }
+to_shmem = { path = "../to_shmem" }
+to_shmem_derive = { path = "../to_shmem_derive" }
--- a/servo/components/style_traits/lib.rs
+++ b/servo/components/style_traits/lib.rs
@@ -23,16 +23,19 @@ extern crate selectors;
 #[cfg(feature = "servo")]
 #[macro_use]
 extern crate serde;
 extern crate servo_arc;
 #[cfg(feature = "servo")]
 extern crate servo_atoms;
 #[cfg(feature = "servo")]
 extern crate servo_url;
+extern crate to_shmem;
+#[macro_use]
+extern crate to_shmem_derive;
 #[cfg(feature = "servo")]
 extern crate webrender_api;
 #[cfg(feature = "servo")]
 pub use webrender_api::DevicePixel;
 
 use cssparser::{CowRcStr, Token};
 use selectors::parser::SelectorParseErrorKind;
 #[cfg(feature = "servo")]
--- a/servo/components/style_traits/values.rs
+++ b/servo/components/style_traits/values.rs
@@ -436,17 +436,17 @@ impl_to_css_for_predefined_type!(::csspa
 impl_to_css_for_predefined_type!(::cssparser::Color);
 impl_to_css_for_predefined_type!(::cssparser::UnicodeRange);
 
 /// Define an enum type with unit variants that each correspond to a CSS keyword.
 macro_rules! define_css_keyword_enum {
     (pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => {
         #[allow(missing_docs)]
         #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-        #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+        #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToShmem)]
         pub enum $name {
             $($variant),+
         }
 
         impl $name {
             /// Parse this property from a CSS input stream.
             pub fn parse<'i, 't>(input: &mut ::cssparser::Parser<'i, 't>)
                                  -> Result<$name, $crate::ParseError<'i>> {
@@ -492,17 +492,17 @@ macro_rules! define_css_keyword_enum {
 }
 
 /// Helper types for the handling of specified values.
 pub mod specified {
     use crate::ParsingMode;
 
     /// Whether to allow negative lengths or not.
     #[repr(u8)]
-    #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd)]
+    #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, ToShmem)]
     pub enum AllowedNumericType {
         /// Allow all kind of numeric values.
         All,
         /// Allow only non-negative numeric values.
         NonNegative,
         /// Allow only numeric values greater or equal to 1.0.
         AtLeastOne,
     }
--- a/servo/components/style_traits/viewport.rs
+++ b/servo/components/style_traits/viewport.rs
@@ -75,17 +75,17 @@ impl ToCss for ViewportConstraints {
 
         dest.write_str("; orientation: ")?;
         self.orientation.to_css(dest)?;
         dest.write_str("; }")
     }
 }
 
 /// <https://drafts.csswg.org/css-device-adapt/#descdef-viewport-zoom>
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq, ToShmem)]
 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
 pub enum Zoom {
     /// A number value.
     Number(f32),
     /// A percentage value.
     Percentage(f32),
     /// The `auto` keyword.
     Auto,