+2012-01-23 Andreas Kling <awesomekling@apple.com>
+
+ Move m_rootEditableElementForSelectionOnMouseDown off of HTMLAnchorElement.
+ <http://webkit.org/b/76833>
+
+ Reviewed by Antti Koivisto.
+
+ Move HTMLAnchorElement::m_rootEditableElementForSelectionOnMouseDown to a rare
+ data-style hashmap, effectively shrinking HTMLAnchorElement by one CPU word.
+
+ The pointer is only used during interactive event handling, so it shouldn't have
+ any noticeable effects on web performance.
+
+ This reduces memory consumption by 256 kB (on 64-bit) when viewing the full
+ HTML5 spec at <http://whatwg.org/c>.
+
+ * html/HTMLAnchorElement.cpp:
+ (WebCore::HTMLAnchorElement::HTMLAnchorElement):
+ (WebCore::HTMLAnchorElement::~HTMLAnchorElement):
+ (WebCore::HTMLAnchorElement::defaultEventHandler):
+ (WebCore::HTMLAnchorElement::treatLinkAsLiveForEventType):
+ (WebCore::rootEditableElementMap):
+ (WebCore::HTMLAnchorElement::rootEditableElementForSelectionOnMouseDown):
+ (WebCore::HTMLAnchorElement::setRootEditableElementForSelectionOnMouseDown):
+ * html/HTMLAnchorElement.h:
+
2012-01-23 Antti Koivisto <antti@apple.com>
Eliminate CSSElementStyleDeclaration subclasses
HTMLAnchorElement::HTMLAnchorElement(const QualifiedName& tagName, Document* document)
: HTMLElement(tagName, document)
+ , m_hasRootEditableElementForSelectionOnMouseDown(false)
, m_wasShiftKeyDownOnMouseDown(false)
, m_linkRelations(0)
, m_cachedVisitedLinkHash(0)
return adoptRef(new HTMLAnchorElement(tagName, document));
}
+HTMLAnchorElement::~HTMLAnchorElement()
+{
+ clearRootEditableElementForSelectionOnMouseDown();
+}
+
// This function does not allow leading spaces before the port number.
static unsigned parsePortFromStringPosition(const String& value, unsigned portStart, unsigned& portEnd)
{
// This keeps track of the editable block that the selection was in (if it was in one) just before the link was clicked
// for the LiveWhenNotFocused editable link behavior
if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() != RightButton && document()->frame() && document()->frame()->selection()) {
- m_rootEditableElementForSelectionOnMouseDown = document()->frame()->selection()->rootEditableElement();
+ setRootEditableElementForSelectionOnMouseDown(document()->frame()->selection()->rootEditableElement());
m_wasShiftKeyDownOnMouseDown = static_cast<MouseEvent*>(event)->shiftKey();
} else if (event->type() == eventNames().mouseoverEvent) {
// These are cleared on mouseover and not mouseout because their values are needed for drag events,
// but drag events happen after mouse out events.
- m_rootEditableElementForSelectionOnMouseDown = 0;
+ clearRootEditableElementForSelectionOnMouseDown();
m_wasShiftKeyDownOnMouseDown = false;
}
}
// If the selection prior to clicking on this link resided in the same editable block as this link,
// and the shift key isn't pressed, we don't want to follow the link.
case EditableLinkLiveWhenNotFocused:
- return eventType == MouseEventWithShiftKey || (eventType == MouseEventWithoutShiftKey && m_rootEditableElementForSelectionOnMouseDown != rootEditableElement());
+ return eventType == MouseEventWithShiftKey || (eventType == MouseEventWithoutShiftKey && rootEditableElementForSelectionOnMouseDown() != rootEditableElement());
case EditableLinkOnlyLiveWithShiftKey:
return eventType == MouseEventWithShiftKey;
}
#endif
+typedef HashMap<const HTMLAnchorElement*, RefPtr<Element> > RootEditableElementMap;
+
+static RootEditableElementMap& rootEditableElementMap()
+{
+ DEFINE_STATIC_LOCAL(RootEditableElementMap, map, ());
+ return map;
+}
+
+Element* HTMLAnchorElement::rootEditableElementForSelectionOnMouseDown() const
+{
+ if (!m_hasRootEditableElementForSelectionOnMouseDown)
+ return 0;
+ return rootEditableElementMap().get(this).get();
+}
+
+void HTMLAnchorElement::clearRootEditableElementForSelectionOnMouseDown()
+{
+ if (!m_hasRootEditableElementForSelectionOnMouseDown)
+ return;
+ rootEditableElementMap().remove(this);
+ m_hasRootEditableElementForSelectionOnMouseDown = false;
+}
+
+void HTMLAnchorElement::setRootEditableElementForSelectionOnMouseDown(Element* element)
+{
+ if (!element) {
+ clearRootEditableElementForSelectionOnMouseDown();
+ return;
+ }
+
+ rootEditableElementMap().set(this, element);
+ m_hasRootEditableElementForSelectionOnMouseDown = true;
+}
+
}
static PassRefPtr<HTMLAnchorElement> create(Document*);
static PassRefPtr<HTMLAnchorElement> create(const QualifiedName&, Document*);
+ virtual ~HTMLAnchorElement();
+
KURL href() const;
void setHref(const AtomicString&);
virtual void setItemValueText(const String&, ExceptionCode&) OVERRIDE;
#endif
- RefPtr<Element> m_rootEditableElementForSelectionOnMouseDown;
+ Element* rootEditableElementForSelectionOnMouseDown() const;
+ void setRootEditableElementForSelectionOnMouseDown(Element*);
+ void clearRootEditableElementForSelectionOnMouseDown();
+
+ bool m_hasRootEditableElementForSelectionOnMouseDown : 1;
bool m_wasShiftKeyDownOnMouseDown : 1;
- uint32_t m_linkRelations : 31;
+ uint32_t m_linkRelations : 30;
mutable LinkHash m_cachedVisitedLinkHash;
};