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.
This commit is contained in:
Alan Jeffrey 2015-11-06 09:48:32 -06:00
parent 4aa6a76f57
commit 64a50bcf56
2 changed files with 30 additions and 7 deletions

View file

@ -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(),

View file

@ -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);