Skip to content

Commit

Permalink
Auto merge of #11318 - mitchhentges:1471-cache-tag-name, r=<try>
Browse files Browse the repository at this point in the history
Compute tag_name a maximum of once per document owner

Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data:
- [x] `./mach build -d` does not report any errors
- [X] `./mach test-tidy --faster` does not report any errors
- [X] These changes fix #1471 (github issue number if applicable).

Either:
- [X] These changes do not require tests because no new functionality was added, just a reorganization and caching of existing functionality

Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11318)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Jul 20, 2016
2 parents 86ed7bf + cc67a80 commit 3bd2b54
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 15 deletions.
72 changes: 61 additions & 11 deletions components/script/dom/element.rs
Expand Up @@ -103,6 +103,7 @@ use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage};
pub struct Element {
node: Node,
local_name: Atom,
tag_name: TagName,
namespace: Namespace,
prefix: Option<DOMString>,
attrs: DOMRefCell<Vec<JS<Attr>>>,
Expand Down Expand Up @@ -165,6 +166,7 @@ impl Element {
Element {
node: Node::new_inherited(document),
local_name: local_name,
tag_name: TagName::new(),
namespace: namespace,
prefix: prefix,
attrs: DOMRefCell::new(vec![]),
Expand Down Expand Up @@ -1366,17 +1368,20 @@ impl ElementMethods for Element {

// https://dom.spec.whatwg.org/#dom-element-tagname
fn TagName(&self) -> DOMString {
let qualified_name = match self.prefix {
Some(ref prefix) => {
Cow::Owned(format!("{}:{}", &**prefix, &*self.local_name))
},
None => Cow::Borrowed(&*self.local_name)
};
DOMString::from(if self.html_element_in_html_document() {
qualified_name.to_ascii_uppercase()
} else {
qualified_name.into_owned()
})
let name = self.tag_name.or_init(|| {
let qualified_name = match self.prefix {
Some(ref prefix) => {
Cow::Owned(format!("{}:{}", &**prefix, &*self.local_name))
},
None => Cow::Borrowed(&*self.local_name)
};
if self.html_element_in_html_document() {
Atom::from(qualified_name.to_ascii_uppercase())
} else {
Atom::from(qualified_name)
}
});
DOMString::from(&*name)
}

// https://dom.spec.whatwg.org/#dom-element-id
Expand Down Expand Up @@ -2218,6 +2223,14 @@ impl VirtualMethods for Element {
}
}
}

fn adopting_steps(&self, old_doc: &Document) {
self.super_type().unwrap().adopting_steps(old_doc);

if document_from_node(self).is_html_document() != old_doc.is_html_document() {
self.tag_name.clear();
}
}
}

impl<'a> ::selectors::MatchAttrGeneric for Root<Element> {
Expand Down Expand Up @@ -2681,3 +2694,40 @@ impl AtomicElementFlags {
self.0.fetch_or(flags.bits() as usize, Ordering::Relaxed);
}
}

/// A holder for an element's "tag name", which will be lazily
/// resolved and cached. Should be reset when the document
/// owner changes.
#[derive(JSTraceable, HeapSizeOf)]
struct TagName {
ptr: DOMRefCell<Option<Atom>>,
}

impl TagName {
fn new() -> TagName {
TagName { ptr: DOMRefCell::new(None) }
}

/// Retrieve a copy of the current inner value. If it is `None`, it is
/// initialized with the result of `cb` first.
#[allow(unsafe_code)]
fn or_init<F>(&self, cb: F) -> Atom
where F: FnOnce() -> Atom
{
match &mut *self.ptr.borrow_mut() {
&mut Some(ref name) => name.clone(),
ptr => {
let name = cb();
*ptr = Some(name.clone());
name
}
}
}

/// Clear the cached tag name, so that it will be re-calculated the
/// next time that `or_init()` is called.
#[allow(unsafe_code)]
fn clear(&self) {
*self.ptr.borrow_mut() = None;
}
}
8 changes: 4 additions & 4 deletions tests/unit/script/size_of.rs
Expand Up @@ -40,10 +40,10 @@ macro_rules! sizeof_checker (
// Update the sizes here
sizeof_checker!(size_event_target, EventTarget, 40);
sizeof_checker!(size_node, Node, 160);
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_element, Element, 336);
sizeof_checker!(size_htmlelement, HTMLElement, 352);
sizeof_checker!(size_div, HTMLDivElement, 352);
sizeof_checker!(size_span, HTMLSpanElement, 352);
sizeof_checker!(size_text, Text, 192);
sizeof_checker!(size_characterdata, CharacterData, 192);
sizeof_checker!(size_servothreadsafelayoutnode, ServoThreadSafeLayoutNode, 16);

0 comments on commit 3bd2b54

Please sign in to comment.