Auto merge of #6188 - Manishearth:sizeof, r=nnethercote

Fixes #5914

r? @nnethercote for the gfx changes

r? @kmcallister or @jdm for the plugin

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6188)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-06-02 23:48:03 -05:00
commit 2ca606aaba
13 changed files with 206 additions and 127 deletions

View file

@ -24,10 +24,10 @@ use text::glyph::CharIndex;
use text::TextRun; use text::TextRun;
use azure::azure::AzFloat; use azure::azure::AzFloat;
use azure::azure_hl::{Color}; use azure::azure_hl::Color;
use collections::linked_list::{self, LinkedList}; use collections::linked_list::{self, LinkedList};
use geom::{Matrix2D, Point2D, Rect, SideOffsets2D, Size2D, Matrix4}; use geom::{Point2D, Rect, SideOffsets2D, Size2D, Matrix2D, Matrix4};
use geom::approxeq::ApproxEq; use geom::approxeq::ApproxEq;
use geom::num::Zero; use geom::num::Zero;
use libc::uintptr_t; use libc::uintptr_t;
@ -66,7 +66,7 @@ const MIN_INDENTATION_LENGTH: usize = 4;
/// Because the script task's GC does not trace layout, node data cannot be safely stored in layout /// Because the script task's GC does not trace layout, node data cannot be safely stored in layout
/// data structures. Also, layout code tends to be faster when the DOM is not being accessed, for /// data structures. Also, layout code tends to be faster when the DOM is not being accessed, for
/// locality reasons. Using `OpaqueNode` enforces this invariant. /// locality reasons. Using `OpaqueNode` enforces this invariant.
#[derive(Clone, PartialEq, Copy, Debug)] #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
pub struct OpaqueNode(pub uintptr_t); pub struct OpaqueNode(pub uintptr_t);
impl OpaqueNode { impl OpaqueNode {
@ -82,6 +82,7 @@ impl OpaqueNode {
/// ///
/// TODO(pcwalton): We could reduce the size of this structure with a more "skip list"-like /// TODO(pcwalton): We could reduce the size of this structure with a more "skip list"-like
/// structure, omitting several pointers and lengths. /// structure, omitting several pointers and lengths.
#[derive(HeapSizeOf)]
pub struct DisplayList { pub struct DisplayList {
/// The border and backgrounds for the root of this stacking context: steps 1 and 2. /// The border and backgrounds for the root of this stacking context: steps 1 and 2.
pub background_and_borders: LinkedList<DisplayItem>, pub background_and_borders: LinkedList<DisplayItem>,
@ -218,24 +219,14 @@ impl DisplayList {
} }
} }
impl HeapSizeOf for DisplayList { #[derive(HeapSizeOf)]
fn heap_size_of_children(&self) -> usize {
self.background_and_borders.heap_size_of_children() +
self.block_backgrounds_and_borders.heap_size_of_children() +
self.floats.heap_size_of_children() +
self.content.heap_size_of_children() +
self.positioned_content.heap_size_of_children() +
self.outlines.heap_size_of_children() +
self.children.heap_size_of_children()
}
}
/// Represents one CSS stacking context, which may or may not have a hardware layer. /// Represents one CSS stacking context, which may or may not have a hardware layer.
pub struct StackingContext { pub struct StackingContext {
/// The display items that make up this stacking context. /// The display items that make up this stacking context.
pub display_list: Box<DisplayList>, pub display_list: Box<DisplayList>,
/// The layer for this stacking context, if there is one. /// The layer for this stacking context, if there is one.
#[ignore_heap_size_of = "FIXME(njn): should measure this at some point"]
pub layer: Option<Arc<PaintLayer>>, pub layer: Option<Arc<PaintLayer>>,
/// The position and size of this stacking context. /// The position and size of this stacking context.
@ -588,14 +579,6 @@ impl StackingContext {
} }
} }
impl HeapSizeOf for StackingContext {
fn heap_size_of_children(&self) -> usize {
self.display_list.heap_size_of_children()
// FIXME(njn): other fields may be measured later, esp. `layer`
}
}
/// Returns the stacking context in the given tree of stacking contexts with a specific layer ID. /// Returns the stacking context in the given tree of stacking contexts with a specific layer ID.
pub fn find_stacking_context_with_layer_id(this: &Arc<StackingContext>, layer_id: LayerId) pub fn find_stacking_context_with_layer_id(this: &Arc<StackingContext>, layer_id: LayerId)
-> Option<Arc<StackingContext>> { -> Option<Arc<StackingContext>> {
@ -615,7 +598,7 @@ pub fn find_stacking_context_with_layer_id(this: &Arc<StackingContext>, layer_id
} }
/// One drawing command in the list. /// One drawing command in the list.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub enum DisplayItem { pub enum DisplayItem {
SolidColorClass(Box<SolidColorDisplayItem>), SolidColorClass(Box<SolidColorDisplayItem>),
TextClass(Box<TextDisplayItem>), TextClass(Box<TextDisplayItem>),
@ -627,7 +610,7 @@ pub enum DisplayItem {
} }
/// Information common to all display items. /// Information common to all display items.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub struct BaseDisplayItem { pub struct BaseDisplayItem {
/// The boundaries of the display item, in layer coordinates. /// The boundaries of the display item, in layer coordinates.
pub bounds: Rect<Au>, pub bounds: Rect<Au>,
@ -651,17 +634,11 @@ impl BaseDisplayItem {
} }
} }
impl HeapSizeOf for BaseDisplayItem {
fn heap_size_of_children(&self) -> usize {
self.metadata.heap_size_of_children() +
self.clip.heap_size_of_children()
}
}
/// A clipping region for a display item. Currently, this can describe rectangles, rounded /// A clipping region for a display item. Currently, this can describe rectangles, rounded
/// rectangles (for `border-radius`), or arbitrary intersections of the two. Arbitrary transforms /// rectangles (for `border-radius`), or arbitrary intersections of the two. Arbitrary transforms
/// are not supported because those are handled by the higher-level `StackingContext` abstraction. /// are not supported because those are handled by the higher-level `StackingContext` abstraction.
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug, HeapSizeOf)]
pub struct ClippingRegion { pub struct ClippingRegion {
/// The main rectangular region. This does not include any corners. /// The main rectangular region. This does not include any corners.
pub main: Rect<Au>, pub main: Rect<Au>,
@ -675,7 +652,7 @@ pub struct ClippingRegion {
/// A complex clipping region. These don't as easily admit arbitrary intersection operations, so /// A complex clipping region. These don't as easily admit arbitrary intersection operations, so
/// they're stored in a list over to the side. Currently a complex clipping region is just a /// they're stored in a list over to the side. Currently a complex clipping region is just a
/// rounded rectangle, but the CSS WGs will probably make us throw more stuff in here eventually. /// rounded rectangle, but the CSS WGs will probably make us throw more stuff in here eventually.
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug, HeapSizeOf)]
pub struct ComplexClippingRegion { pub struct ComplexClippingRegion {
/// The boundaries of the rectangle. /// The boundaries of the rectangle.
pub rect: Rect<Au>, pub rect: Rect<Au>,
@ -783,22 +760,11 @@ impl ClippingRegion {
} }
} }
impl HeapSizeOf for ClippingRegion {
fn heap_size_of_children(&self) -> usize {
self.complex.heap_size_of_children()
}
}
impl HeapSizeOf for ComplexClippingRegion {
fn heap_size_of_children(&self) -> usize {
0
}
}
/// Metadata attached to each display item. This is useful for performing auxiliary tasks with /// Metadata attached to each display item. This is useful for performing auxiliary tasks with
/// the display list involving hit testing: finding the originating DOM node and determining the /// the display list involving hit testing: finding the originating DOM node and determining the
/// cursor to use when the element is hovered over. /// cursor to use when the element is hovered over.
#[derive(Clone, Copy)] #[derive(Clone, Copy, HeapSizeOf)]
pub struct DisplayItemMetadata { pub struct DisplayItemMetadata {
/// The DOM node from which this display item originated. /// The DOM node from which this display item originated.
pub node: OpaqueNode, pub node: OpaqueNode,
@ -826,14 +792,8 @@ impl DisplayItemMetadata {
} }
} }
impl HeapSizeOf for DisplayItemMetadata {
fn heap_size_of_children(&self) -> usize {
0
}
}
/// Paints a solid color. /// Paints a solid color.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub struct SolidColorDisplayItem { pub struct SolidColorDisplayItem {
/// Fields common to all display items. /// Fields common to all display items.
pub base: BaseDisplayItem, pub base: BaseDisplayItem,
@ -842,19 +802,14 @@ pub struct SolidColorDisplayItem {
pub color: Color, pub color: Color,
} }
impl HeapSizeOf for SolidColorDisplayItem {
fn heap_size_of_children(&self) -> usize {
self.base.heap_size_of_children()
}
}
/// Paints text. /// Paints text.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub struct TextDisplayItem { pub struct TextDisplayItem {
/// Fields common to all display items. /// Fields common to all display items.
pub base: BaseDisplayItem, pub base: BaseDisplayItem,
/// The text run. /// The text run.
#[ignore_heap_size_of = "Because it is non-owning"]
pub text_run: Arc<Box<TextRun>>, pub text_run: Arc<Box<TextRun>>,
/// The range of text within the text run. /// The range of text within the text run.
@ -873,14 +828,7 @@ pub struct TextDisplayItem {
pub blur_radius: Au, pub blur_radius: Au,
} }
impl HeapSizeOf for TextDisplayItem { #[derive(Clone, Eq, PartialEq, HeapSizeOf)]
fn heap_size_of_children(&self) -> usize {
self.base.heap_size_of_children()
// We exclude `text_run` because it is non-owning.
}
}
#[derive(Clone, Eq, PartialEq)]
pub enum TextOrientation { pub enum TextOrientation {
Upright, Upright,
SidewaysLeft, SidewaysLeft,
@ -888,9 +836,10 @@ pub enum TextOrientation {
} }
/// Paints an image. /// Paints an image.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub struct ImageDisplayItem { pub struct ImageDisplayItem {
pub base: BaseDisplayItem, pub base: BaseDisplayItem,
#[ignore_heap_size_of = "Because it is non-owning"]
pub image: Arc<Image>, pub image: Arc<Image>,
/// The dimensions to which the image display item should be stretched. If this is smaller than /// The dimensions to which the image display item should be stretched. If this is smaller than
@ -903,12 +852,6 @@ pub struct ImageDisplayItem {
pub image_rendering: image_rendering::T, pub image_rendering: image_rendering::T,
} }
impl HeapSizeOf for ImageDisplayItem {
fn heap_size_of_children(&self) -> usize {
self.base.heap_size_of_children()
// We exclude `image` here because it is non-owning.
}
}
/// Paints a gradient. /// Paints a gradient.
#[derive(Clone)] #[derive(Clone)]
@ -926,6 +869,7 @@ pub struct GradientDisplayItem {
pub stops: Vec<GradientStop>, pub stops: Vec<GradientStop>,
} }
impl HeapSizeOf for GradientDisplayItem { impl HeapSizeOf for GradientDisplayItem {
fn heap_size_of_children(&self) -> usize { fn heap_size_of_children(&self) -> usize {
use libc::c_void; use libc::c_void;
@ -941,7 +885,7 @@ impl HeapSizeOf for GradientDisplayItem {
/// Paints a border. /// Paints a border.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub struct BorderDisplayItem { pub struct BorderDisplayItem {
/// Fields common to all display items. /// Fields common to all display items.
pub base: BaseDisplayItem, pub base: BaseDisplayItem,
@ -961,16 +905,10 @@ pub struct BorderDisplayItem {
pub radius: BorderRadii<Au>, pub radius: BorderRadii<Au>,
} }
impl HeapSizeOf for BorderDisplayItem {
fn heap_size_of_children(&self) -> usize {
self.base.heap_size_of_children()
}
}
/// Information about the border radii. /// Information about the border radii.
/// ///
/// TODO(pcwalton): Elliptical radii. /// TODO(pcwalton): Elliptical radii.
#[derive(Clone, Default, PartialEq, Debug, Copy)] #[derive(Clone, Default, PartialEq, Debug, Copy, HeapSizeOf)]
pub struct BorderRadii<T> { pub struct BorderRadii<T> {
pub top_left: T, pub top_left: T,
pub top_right: T, pub top_right: T,
@ -1000,7 +938,7 @@ impl<T> BorderRadii<T> where T: PartialEq + Zero + Clone {
} }
/// Paints a line segment. /// Paints a line segment.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub struct LineDisplayItem { pub struct LineDisplayItem {
pub base: BaseDisplayItem, pub base: BaseDisplayItem,
@ -1011,14 +949,8 @@ pub struct LineDisplayItem {
pub style: border_style::T pub style: border_style::T
} }
impl HeapSizeOf for LineDisplayItem {
fn heap_size_of_children(&self) -> usize {
self.base.heap_size_of_children()
}
}
/// Paints a box shadow per CSS-BACKGROUNDS. /// Paints a box shadow per CSS-BACKGROUNDS.
#[derive(Clone)] #[derive(Clone, HeapSizeOf)]
pub struct BoxShadowDisplayItem { pub struct BoxShadowDisplayItem {
/// Fields common to all display items. /// Fields common to all display items.
pub base: BaseDisplayItem, pub base: BaseDisplayItem,
@ -1042,14 +974,8 @@ pub struct BoxShadowDisplayItem {
pub clip_mode: BoxShadowClipMode, pub clip_mode: BoxShadowClipMode,
} }
impl HeapSizeOf for BoxShadowDisplayItem {
fn heap_size_of_children(&self) -> usize {
self.base.heap_size_of_children()
}
}
/// How a box shadow should be clipped. /// How a box shadow should be clipped.
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf)]
pub enum BoxShadowClipMode { pub enum BoxShadowClipMode {
/// No special clipping should occur. This is used for (shadowed) text decorations. /// No special clipping should occur. This is used for (shadowed) text decorations.
None, None,
@ -1210,17 +1136,4 @@ impl fmt::Debug for DisplayItem {
} }
} }
impl HeapSizeOf for DisplayItem {
fn heap_size_of_children(&self) -> usize {
match *self {
SolidColorClass(ref item) => item.heap_size_of_children(),
TextClass(ref item) => item.heap_size_of_children(),
ImageClass(ref item) => item.heap_size_of_children(),
BorderClass(ref item) => item.heap_size_of_children(),
GradientClass(ref item) => item.heap_size_of_children(),
LineClass(ref item) => item.heap_size_of_children(),
BoxShadowClass(ref item) => item.heap_size_of_children(),
}
}
}

View file

@ -6,7 +6,8 @@
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(collections)] #![feature(collections)]
#![feature(core)] #![feature(core)]
#![feature(plugin)] #![feature(plugin, custom_attribute)]
#![feature(custom_derive)]
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(std_misc)] #![feature(std_misc)]
#![feature(str_char)] #![feature(str_char)]

View file

@ -519,6 +519,7 @@ int_range_index! {
#[derive(RustcEncodable)] #[derive(RustcEncodable)]
#[doc = "An index that refers to a character in a text run. This could \ #[doc = "An index that refers to a character in a text run. This could \
point to the middle of a glyph."] point to the middle of a glyph."]
#[derive(HeapSizeOf)]
struct CharIndex(isize) struct CharIndex(isize)
} }

View file

@ -0,0 +1,81 @@
/* 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 http://mozilla.org/MPL/2.0/. */
//! Handles the auto-deriving for `#[derive(HeapSizeOf)]`
//!
//! This provides the `#[derive(HeapSizeOf)]` decorator, which
//! generates a `HeapSizeOf` implementation that adds up
//! calls to heap_size_of_children() for all the fields
//! of a struct or enum variant.
//!
//! Fields marked `#[ignore_heap_size_of = "reason"]` will
//! be ignored in this calculation. Providing a reason is compulsory.
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::codemap::Span;
use syntax::ptr::P;
use syntax::ast::*;
use syntax::attr::AttrMetaMethods;
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::*;
pub fn expand_heap_size(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem,
item: &Annotatable, push: &mut FnMut(Annotatable)) {
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
path: ty::Path::new(vec!("util", "mem", "HeapSizeOf")),
additional_bounds: Vec::new(),
generics: ty::LifetimeBounds::empty(),
methods: vec![
MethodDef {
name: "heap_size_of_children",
generics: ty::LifetimeBounds::empty(),
explicit_self: ty::borrowed_explicit_self(),
args: vec!(),
ret_ty: ty::Literal(ty::Path::new_local("usize")),
attributes: vec!(),
is_unsafe: false,
combine_substructure: combine_substructure(Box::new(heap_size_substructure))
}
],
associated_types: vec![],
};
trait_def.expand(cx, mitem, item, push)
}
/// Defines how the implementation for `heap_size_of_children()` is to be generated.
fn heap_size_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
let fields = match *substr.fields {
Struct(ref fs) | EnumMatching(_, _, ref fs) => fs,
_ => cx.span_bug(trait_span, "impossible substructure in `#[derive(HeapSizeOf)]`")
};
fields.iter().fold(cx.expr_usize(trait_span, 0), |acc, ref item| {
if item.attrs.iter()
.find(|ref a| {
if a.check_name("ignore_heap_size_of") {
match a.node.value.node {
MetaNameValue(..) => (),
_ => cx.span_err(a.span, "#[ignore_heap_size_of] \
should have an explanation, \
e.g. #[ignore_heap_size_of = \"\"]")
}
true
} else {
false
}
})
.is_some() {
acc
} else {
cx.expr_binary(item.span, BiAdd, acc,
cx.expr_method_call(item.span,
item.self_.clone(),
substr.method_ident,
Vec::new()))
}
})
}

View file

@ -8,10 +8,10 @@
//! //!
//! - `#[privatize]` : Forces all fields in a struct/enum to be private //! - `#[privatize]` : Forces all fields in a struct/enum to be private
//! - `#[jstraceable]` : Auto-derives an implementation of `JSTraceable` for a struct in the script crate //! - `#[jstraceable]` : Auto-derives an implementation of `JSTraceable` for a struct in the script crate
//! - `#[must_root]` : Prevents data of the marked type from being used on the stack. See the lints module for more //! - `#[must_root]` : Prevents data of the marked type from being used on the stack.
//! details //! See the lints module for more details
//! - `#[dom_struct]` : Implies `#[privatize]`,`#[jstraceable]`, and `#[must_root]`. //! - `#[dom_struct]` : Implies `#[privatize]`,`#[jstraceable]`, and `#[must_root]`.
//! Use this for structs that correspond to a DOM type //! Use this for structs that correspond to a DOM type
#![feature(plugin_registrar, quote, plugin, box_syntax, rustc_private, collections)] #![feature(plugin_registrar, quote, plugin, box_syntax, rustc_private, collections)]
@ -31,6 +31,8 @@ use syntax::parse::token::intern;
// Public for documentation to show up // Public for documentation to show up
/// Handles the auto-deriving for `#[jstraceable]` /// Handles the auto-deriving for `#[jstraceable]`
pub mod jstraceable; pub mod jstraceable;
/// Handles the auto-deriving for `#[derive(HeapSizeOf)]`
pub mod heap_size;
/// Autogenerates implementations of Reflectable on DOM structs /// Autogenerates implementations of Reflectable on DOM structs
pub mod reflector; pub mod reflector;
pub mod lints; pub mod lints;
@ -43,6 +45,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(intern("dom_struct"), MultiModifier(box jstraceable::expand_dom_struct)); reg.register_syntax_extension(intern("dom_struct"), MultiModifier(box jstraceable::expand_dom_struct));
reg.register_syntax_extension(intern("jstraceable"), MultiDecorator(box jstraceable::expand_jstraceable)); reg.register_syntax_extension(intern("jstraceable"), MultiDecorator(box jstraceable::expand_jstraceable));
reg.register_syntax_extension(intern("_generate_reflector"), MultiDecorator(box reflector::expand_reflector)); reg.register_syntax_extension(intern("_generate_reflector"), MultiDecorator(box reflector::expand_reflector));
reg.register_syntax_extension(intern("derive_HeapSizeOf"), MultiDecorator(box heap_size::expand_heap_size));
reg.register_macro("to_lower", casing::expand_lower); reg.register_macro("to_lower", casing::expand_lower);
reg.register_macro("to_upper", casing::expand_upper); reg.register_macro("to_upper", casing::expand_upper);
reg.register_lint_pass(box lints::transmute_type::TransmutePass as LintPassObject); reg.register_lint_pass(box lints::transmute_type::TransmutePass as LintPassObject);

View file

@ -1280,6 +1280,7 @@ name = "util_tests"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"geom 0.1.0 (git+https://github.com/servo/rust-geom)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)",
"plugins 0.0.1",
"util 0.0.1", "util 0.0.1",
] ]

View file

@ -9,8 +9,9 @@
#![feature(collections)] #![feature(collections)]
#![feature(hash)] #![feature(hash)]
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(custom_attribute, custom_derive)]
#![plugin(string_cache_plugin)] #![plugin(string_cache_plugin)]
#![plugin(plugins)]
#[macro_use] extern crate log; #[macro_use] extern crate log;
#[macro_use] extern crate bitflags; #[macro_use] extern crate bitflags;

View file

@ -1027,8 +1027,8 @@ pub mod longhands {
#[inline] #[inline]
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
computed_value::T(vec![ computed_value::T(vec![
("\u{201c}".to_string(), "\u{201d}".to_string()), ("\u{201c}".to_owned(), "\u{201d}".to_owned()),
("\u{2018}".to_string(), "\u{2019}".to_string()), ("\u{2018}".to_owned(), "\u{2019}".to_owned()),
]) ])
} }
@ -2935,7 +2935,7 @@ pub mod longhands {
use values::CSSFloat; use values::CSSFloat;
use values::specified::{Angle}; use values::specified::{Angle};
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug, HeapSizeOf)]
pub enum Filter { pub enum Filter {
Blur(Au), Blur(Au),
Brightness(CSSFloat), Brightness(CSSFloat),
@ -2948,7 +2948,7 @@ pub mod longhands {
Sepia(CSSFloat), Sepia(CSSFloat),
} }
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug, HeapSizeOf)]
pub struct T { pub filters: Vec<Filter> } pub struct T { pub filters: Vec<Filter> }
impl T { impl T {
@ -3631,7 +3631,7 @@ pub mod longhands {
use cssparser::ToCss; use cssparser::ToCss;
use std::fmt; use std::fmt;
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq, HeapSizeOf)]
pub enum T { pub enum T {
Auto, Auto,
CrispEdges, CrispEdges,

View file

@ -12,7 +12,7 @@ macro_rules! define_css_keyword_enum {
}; };
($name: ident: $( $css: expr => $variant: ident ),+) => { ($name: ident: $( $css: expr => $variant: ident ),+) => {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug)] #[derive(Clone, Eq, PartialEq, Copy, Hash, RustcEncodable, Debug, HeapSizeOf)]
pub enum $name { pub enum $name {
$( $variant ),+ $( $variant ),+
} }
@ -43,7 +43,7 @@ macro_rules! define_numbered_css_keyword_enum {
}; };
($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => { ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Copy, RustcEncodable, Debug)] #[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Copy, RustcEncodable, Debug, HeapSizeOf)]
pub enum $name { pub enum $name {
$( $variant = $value ),+ $( $variant = $value ),+
} }
@ -68,7 +68,6 @@ macro_rules! define_numbered_css_keyword_enum {
} }
} }
pub type CSSFloat = f32; pub type CSSFloat = f32;
@ -607,7 +606,7 @@ pub mod specified {
} }
} }
#[derive(Clone, PartialEq, PartialOrd, Copy, Debug)] #[derive(Clone, PartialEq, PartialOrd, Copy, Debug, HeapSizeOf)]
pub struct Angle(pub CSSFloat); pub struct Angle(pub CSSFloat);
impl ToCss for Angle { impl ToCss for Angle {

View file

@ -9,6 +9,13 @@ use std::collections::LinkedList;
use std::mem::transmute; use std::mem::transmute;
use std::sync::Arc; use std::sync::Arc;
use azure::azure_hl::Color;
use cursor::Cursor;
use geom::{Point2D, Rect, SideOffsets2D, Size2D, Matrix2D, Matrix4};
use geometry::Au;
use range::Range;
extern { extern {
// Get the size of a heap block. // Get the size of a heap block.
// //
@ -35,9 +42,6 @@ pub fn heap_size_of(ptr: *const c_void) -> usize {
// return multiple measurements -- e.g. measure text separately from images -- are also possible, // return multiple measurements -- e.g. measure text separately from images -- are also possible,
// and should be used when appropriate. // and should be used when appropriate.
// //
// FIXME(njn): it would be nice to be able to derive this trait automatically, given that
// implementations are mostly repetitive and mechanical.
//
pub trait HeapSizeOf { pub trait HeapSizeOf {
/// Measure the size of any heap-allocated structures that hang off this value, but not the /// Measure the size of any heap-allocated structures that hang off this value, but not the
/// space taken up by the value itself (i.e. what size_of::<T> measures, more or less); that /// space taken up by the value itself (i.e. what size_of::<T> measures, more or less); that
@ -158,3 +162,38 @@ impl<T> Drop for LinkedList2<T> {
fn drop(&mut self) {} fn drop(&mut self) {}
} }
/// For use on types defined in external crates
/// with known heap sizes.
#[macro_export]
macro_rules! known_heap_size(
($size:expr, $($ty:ident),+) => (
$(
impl $crate::mem::HeapSizeOf for $ty {
#[inline(always)]
fn heap_size_of_children(&self) -> usize {
$size
}
}
)+
);
($size: expr, $($ty:ident<$($gen:ident),+>),+) => (
$(
impl<$($gen: $crate::mem::HeapSizeOf),+> $crate::mem::HeapSizeOf for $ty<$($gen),+> {
#[inline(always)]
fn heap_size_of_children(&self) -> usize {
$size
}
}
)+
);
);
known_heap_size!(0, u8, u16, u32, u64, usize);
known_heap_size!(0, i8, i16, i32, i64, isize);
known_heap_size!(0, bool, f32, f64);
known_heap_size!(0, Rect<T>, Point2D<T>, Size2D<T>, Matrix2D<T>, SideOffsets2D<T>, Matrix4<T>);
known_heap_size!(0, Au, Color, Cursor);
known_heap_size!(0, Range<T>);

View file

@ -11,5 +11,9 @@ doctest = false
[dependencies.util] [dependencies.util]
path = "../../../components/util" path = "../../../components/util"
[dependencies.plugins]
path = "../../../components/plugins"
[dependencies.geom] [dependencies.geom]
git = "https://github.com/servo/rust-geom" git = "https://github.com/servo/rust-geom"

View file

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![feature(plugin, custom_derive, custom_attributes)]
#![plugin(plugins)]
extern crate util; extern crate util;
extern crate geom; extern crate geom;
@ -9,3 +11,4 @@ extern crate geom;
#[cfg(test)] mod logical_geometry; #[cfg(test)] mod logical_geometry;
#[cfg(test)] mod task; #[cfg(test)] mod task;
#[cfg(test)] mod vec; #[cfg(test)] mod vec;
#[cfg(test)] mod mem;

33
tests/unit/util/mem.rs Normal file
View file

@ -0,0 +1,33 @@
/* 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 http://mozilla.org/MPL/2.0/. */
use util::mem::HeapSizeOf;
struct Four;
impl HeapSizeOf for Four {
fn heap_size_of_children(&self) -> usize {
4
}
}
#[derive(HeapSizeOf)]
struct Eight(Four, Four, bool, bool, bool);
#[derive(HeapSizeOf)]
enum EightOrFour {
Eight(Eight),
Four(Four),
Zero(u8)
}
#[test]
fn test_heap_size() {
assert_eq!(Four.heap_size_of_children(), 4);
let eight = Eight(Four, Four, true, true, true);
assert_eq!(eight.heap_size_of_children(), 8);
assert_eq!(EightOrFour::Eight(eight).heap_size_of_children(), 8);
assert_eq!(EightOrFour::Four(Four).heap_size_of_children(), 4);
assert_eq!(EightOrFour::Zero(1).heap_size_of_children(), 0);
}