aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Jeffrey <ajeffrey@mozilla.com>2015-11-06 09:48:32 -0600
committerAlan Jeffrey <ajeffrey@mozilla.com>2015-11-06 17:23:16 -0600
commit64a50bcf5640fe202e37e7b93c4932e27ce08c98 (patch)
treeeb7163f0a9441c73026ef126cc550011eae48bb9
parent4aa6a76f5714fa945f1883ae2d658750cc91d6e3 (diff)
downloadservo-64a50bcf5640fe202e37e7b93c4932e27ce08c98.tar.gz
servo-64a50bcf5640fe202e37e7b93c4932e27ce08c98.zip
Added versioning to DOM nodes.
There is now an inclusive_descendants_version field of each node, which increases each time the node, or any of its descendants, is dirtied. This can be used for cache invalidation, by caching a version number and comparting the current version number against the cached version number.
-rw-r--r--components/script/dom/node.rs23
-rw-r--r--tests/unit/script/size_of.rs14
2 files changed, 30 insertions, 7 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index d3eb716d05d..49bb441e21e 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -57,6 +57,7 @@ use selectors::parser::Selector;
use selectors::parser::parse_author_origin_selector_list_from_str;
use std::borrow::ToOwned;
use std::cell::{Cell, Ref, RefCell, RefMut};
+use std::cmp::max;
use std::default::Default;
use std::iter::{self, FilterMap, Peekable};
use std::mem;
@@ -105,6 +106,9 @@ pub struct Node {
/// A bitfield of flags for node items.
flags: Cell<NodeFlags>,
+ /// The maximum version of any inclusive descendant of this node.
+ inclusive_descendants_version: Cell<u64>,
+
/// Layout information. Only the layout task may touch this data.
///
/// Must be sent back to the layout task to be destroyed when this
@@ -489,6 +493,19 @@ impl Node {
}
pub fn dirty_impl(&self, damage: NodeDamage, force_ancestors: bool) {
+
+ // 0. Set version counter
+ // The new version counter is 1 plus the max of the node's current version counter,
+ // its descendants version, and the document's version. Normally, this will just be
+ // the document's version, but we do have to deal with the case where the node has moved
+ // document, so may have a higher version count than its owning document.
+ let doc: Root<Node> = Root::upcast(self.owner_doc());
+ let version = max(self.get_inclusive_descendants_version(), doc.get_inclusive_descendants_version()) + 1;
+ for ancestor in self.inclusive_ancestors() {
+ ancestor.inclusive_descendants_version.set(version);
+ }
+ doc.inclusive_descendants_version.set(version);
+
// 1. Dirty self.
match damage {
NodeDamage::NodeStyleDamaged => {}
@@ -520,6 +537,11 @@ impl Node {
}
}
+ /// The maximum version number of this node's descendants, including itself
+ pub fn get_inclusive_descendants_version(&self) -> u64 {
+ self.inclusive_descendants_version.get()
+ }
+
/// Iterates over this node and all its descendants, in preorder.
pub fn traverse_preorder(&self) -> TreeIterator {
TreeIterator::new(self)
@@ -1284,6 +1306,7 @@ impl Node {
child_list: Default::default(),
children_count: Cell::new(0u32),
flags: Cell::new(flags),
+ inclusive_descendants_version: Cell::new(0),
layout_data: LayoutDataRef::new(),
diff --git a/tests/unit/script/size_of.rs b/tests/unit/script/size_of.rs
index b89ca9dd837..16154bdcc91 100644
--- a/tests/unit/script/size_of.rs
+++ b/tests/unit/script/size_of.rs
@@ -38,10 +38,10 @@ macro_rules! sizeof_checker (
// Update the sizes here
sizeof_checker!(size_event_target, EventTarget, 40);
-sizeof_checker!(size_node, Node, 168);
-sizeof_checker!(size_element, Element, 312);
-sizeof_checker!(size_htmlelement, HTMLElement, 328);
-sizeof_checker!(size_div, HTMLDivElement, 328);
-sizeof_checker!(size_span, HTMLSpanElement, 328);
-sizeof_checker!(size_text, Text, 200);
-sizeof_checker!(size_characterdata, CharacterData, 200);
+sizeof_checker!(size_node, Node, 176);
+sizeof_checker!(size_element, Element, 320);
+sizeof_checker!(size_htmlelement, HTMLElement, 336);
+sizeof_checker!(size_div, HTMLDivElement, 336);
+sizeof_checker!(size_span, HTMLSpanElement, 336);
+sizeof_checker!(size_text, Text, 208);
+sizeof_checker!(size_characterdata, CharacterData, 208);