2010-01-18 Maciej Stachowiak <mjs@apple.com>
authormjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Jan 2010 02:25:21 +0000 (02:25 +0000)
committermjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Jan 2010 02:25:21 +0000 (02:25 +0000)
        Reviewed by Adam Barth.

        Inline functions that are hot in DOM manipulation
        https://bugs.webkit.org/show_bug.cgi?id=33820

        (3% speedup on Dromaeo DOM Core tests)

        * runtime/WeakGCMap.h:
        (JSC::::get): inline
2010-01-18  Maciej Stachowiak  <mjs@apple.com>

        Reviewed by Adam Barth.

        Inline functions that are hot in DOM manipulation
        https://bugs.webkit.org/show_bug.cgi?id=33820

        (3% speedup on Dromaeo DOM Core tests)

        * bindings/js/JSDOMBinding.h:
        (WebCore::currentWorld): Inlined.
        (WebCore::jsString): Inlined String& overload and split off slow case.
        * bindings/js/JSDOMBinding.cpp:
        (WebCore::jsStringSlowCase): Slow case for the above.
        * dom/Document.h:
        (WebCore::Document::isHTMLDocument): Use a bit and an inline method
        instead of a virtual method, since this is so hot and size of Document
        is not a prime concern.
        (WebCore::Document::create): Adapt for above.
        (WebCore::Document::createXHTML): ditto
        * dom/Document.cpp:
        (WebCore::Document::Document): ditto
        * html/HTMLDocument.cpp:
        (WebCore::HTMLDocument::HTMLDocument): ditto
        * html/HTMLDocument.h: ditto
        * loader/PlaceholderDocument.h:
        (WebCore::PlaceholderDocument::PlaceholderDocument): ditto
        * svg/SVGDocument.cpp:
        (WebCore::SVGDocument::SVGDocument): ditto
        * dom/Element.h:
        (WebCore::Element::attributes): Inlined.
        (WebCore::Element::updateId): Inlined.
        * dom/Element.cpp: (Remove inlined methods.)
        * dom/NamedAttrMap.h:
        (WebCore::NamedNodeMap::getAttributeItem): Inlined and split off slow case.
        * dom/NamedAttrMap.cpp:
        (WebCore::NamedNodeMap::getAttributeItemSlowCase): Slow case for the above.
        * inspector/InspectorController.cpp:
        * inspector/InspectorController.h:
        (WebCore::InspectorController::didInsertDOMNode): Inlined so the fast case
        early exit doesn't incur a function call.
        (WebCore::InspectorController::didRemoveDOMNode): ditto
        (WebCore::InspectorController::didModifyDOMAttr): ditto
        * platform/ThreadGlobalData.h:
        (WebCore::threadGlobalData): Inlined.
        * platform/ThreadGlobalData.cpp: (Removed inline methods).
        * platform/Timer.h:
        (WebCore::TimerBase::isActive): Inlined.
        * platform/Timer.cpp: (Removed inline methods).
        * WebCore.xcodeproj/project.pbxproj: Install new heares.
        * WebCore.base.exp: Add appropriate exports.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53514 268f45cc-cd09-0410-ab3c-d52691b4dbfc

23 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/runtime/WeakGCMap.h
WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSDOMBinding.cpp
WebCore/bindings/js/JSDOMBinding.h
WebCore/dom/Document.cpp
WebCore/dom/Document.h
WebCore/dom/Element.cpp
WebCore/dom/Element.h
WebCore/dom/NamedAttrMap.cpp
WebCore/dom/NamedAttrMap.h
WebCore/html/HTMLDocument.cpp
WebCore/html/HTMLDocument.h
WebCore/inspector/InspectorController.cpp
WebCore/inspector/InspectorController.h
WebCore/loader/PlaceholderDocument.h
WebCore/platform/ThreadGlobalData.cpp
WebCore/platform/ThreadGlobalData.h
WebCore/platform/Timer.cpp
WebCore/platform/Timer.h
WebCore/svg/SVGDocument.cpp

index 75c3eaa1595e041e7f61344b9f4ee690f5dfacff..7e86c4dab2fc8c9d07159d8ea70b944d29a555f7 100644 (file)
@@ -1,3 +1,15 @@
+2010-01-18  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Adam Barth.
+
+        Inline functions that are hot in DOM manipulation
+        https://bugs.webkit.org/show_bug.cgi?id=33820
+        
+        (3% speedup on Dromaeo DOM Core tests)
+
+        * runtime/WeakGCMap.h:
+        (JSC::::get): inline
+
 2010-01-19  Laszlo Gombos  <laszlo.1.gombos@nokia.com>
 
         Unreviewed build fix for JIT with RVCT.
index 465cb56749c09acedb1778b76e0eea94b6363073..39a91c5fa59adb605ae37351eaec1723395b1987 100644 (file)
@@ -72,7 +72,7 @@ private:
 };
 
 template<typename KeyType, typename MappedType>
-MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
+inline MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
 {
     MappedType result = m_map.get(key);
     if (result == HashTraits<MappedType>::emptyValue())
index 42f6910484a96b694d03647cc579b8cafd8367ef..d6b71dc487007d4e230ba215cc6cbf4a2e24148d 100644 (file)
@@ -1,3 +1,55 @@
+2010-01-18  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Adam Barth.
+
+        Inline functions that are hot in DOM manipulation
+        https://bugs.webkit.org/show_bug.cgi?id=33820
+
+        (3% speedup on Dromaeo DOM Core tests)
+
+        * bindings/js/JSDOMBinding.h:
+        (WebCore::currentWorld): Inlined.
+        (WebCore::jsString): Inlined String& overload and split off slow case.
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::jsStringSlowCase): Slow case for the above.
+        * dom/Document.h:
+        (WebCore::Document::isHTMLDocument): Use a bit and an inline method
+        instead of a virtual method, since this is so hot and size of Document
+        is not a prime concern.
+        (WebCore::Document::create): Adapt for above.
+        (WebCore::Document::createXHTML): ditto
+        * dom/Document.cpp:
+        (WebCore::Document::Document): ditto
+        * html/HTMLDocument.cpp:
+        (WebCore::HTMLDocument::HTMLDocument): ditto
+        * html/HTMLDocument.h: ditto
+        * loader/PlaceholderDocument.h:
+        (WebCore::PlaceholderDocument::PlaceholderDocument): ditto
+        * svg/SVGDocument.cpp:
+        (WebCore::SVGDocument::SVGDocument): ditto
+        * dom/Element.h:
+        (WebCore::Element::attributes): Inlined.
+        (WebCore::Element::updateId): Inlined.
+        * dom/Element.cpp: (Remove inlined methods.)
+        * dom/NamedAttrMap.h:
+        (WebCore::NamedNodeMap::getAttributeItem): Inlined and split off slow case.
+        * dom/NamedAttrMap.cpp:
+        (WebCore::NamedNodeMap::getAttributeItemSlowCase): Slow case for the above.
+        * inspector/InspectorController.cpp:
+        * inspector/InspectorController.h:
+        (WebCore::InspectorController::didInsertDOMNode): Inlined so the fast case
+        early exit doesn't incur a function call.
+        (WebCore::InspectorController::didRemoveDOMNode): ditto
+        (WebCore::InspectorController::didModifyDOMAttr): ditto
+        * platform/ThreadGlobalData.h:
+        (WebCore::threadGlobalData): Inlined.
+        * platform/ThreadGlobalData.cpp: (Removed inline methods).
+        * platform/Timer.h:
+        (WebCore::TimerBase::isActive): Inlined.
+        * platform/Timer.cpp: (Removed inline methods).
+        * WebCore.xcodeproj/project.pbxproj: Install new heares.
+        * WebCore.base.exp: Add appropriate exports.
+
 2010-01-19  Jon Honeycutt  <jhoneycutt@apple.com>
 
         Chromium build fix.
index de592650f443adf9da5c78f3d2868fee1a75faa7..9b47d3eb00321ec81b2d29c13b8e03a55f7d8d1e 100644 (file)
@@ -139,6 +139,7 @@ __ZN7WebCore10ScrollView17setScrollbarModesENS_13ScrollbarModeES1_
 __ZN7WebCore10ScrollView20setCanHaveScrollbarsEb
 __ZN7WebCore10StringImpl11reverseFindEPS0_ib
 __ZN7WebCore10StringImpl7replaceEtt
+__ZN7WebCore10StringImpl7ustringEv
 __ZN7WebCore10StringImpl8endsWithEPS0_b
 __ZN7WebCore10StringImplD1Ev
 __ZN7WebCore10StringImplcvP8NSStringEv
@@ -378,6 +379,9 @@ __ZN7WebCore16ScriptController11createWorldEv
 __ZN7WebCore16ScriptController13executeScriptERKNS_6StringEb
 __ZN7WebCore16ScriptController18windowScriptObjectEv
 __ZN7WebCore16ScriptController20executeScriptInWorldEPNS_15DOMWrapperWorldERKNS_6StringEb
+__ZN7WebCore16ThreadGlobalData10staticDataE
+__ZN7WebCore16ThreadGlobalDataC1Ev
+__ZN7WebCore16ThreadGlobalDataD1Ev
 __ZN7WebCore16VisibleSelectionC1EPKNS_5RangeENS_9EAffinityE
 __ZN7WebCore16VisibleSelectionC1ERKNS_15VisiblePositionES3_
 __ZN7WebCore16colorFromNSColorEP7NSColor
@@ -385,6 +389,7 @@ __ZN7WebCore16createFullMarkupEPKNS_4NodeE
 __ZN7WebCore16createFullMarkupEPKNS_5RangeE
 __ZN7WebCore16enclosingIntRectERK7_NSRect
 __ZN7WebCore16isEndOfParagraphERKNS_15VisiblePositionE
+__ZN7WebCore16jsStringSlowCaseEPN3JSC9ExecStateERNS0_9WeakGCMapIPNS_10StringImplEPNS0_8JSStringEEES5_
 __ZN7WebCore16threadGlobalDataEv
 __ZN7WebCore17CredentialStorage3getERKNS_15ProtectionSpaceE
 __ZN7WebCore17DOMImplementation14isTextMIMETypeERKNS_6StringE
@@ -985,7 +990,6 @@ __ZNK7WebCore9FrameTree6parentEb
 __ZNK7WebCore9FrameView11needsLayoutEv
 __ZNK7WebCore9PageCache10frameCountEv
 __ZNK7WebCore9PageCache21autoreleasedPageCountEv
-__ZNK7WebCore9TimerBase8isActiveEv
 __ZTVN7WebCore12ChromeClientE
 __ZTVN7WebCore12PluginWidgetE
 __ZTVN7WebCore17FileChooserClientE
index efa8e81c0528b351bf3f34220629b8738f20847b..7ae59a1ee3699b61d24c21764d4cc88f44b0d870 100644 (file)
                7A1E88F5101CC384000C4DF5 /* ScriptArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A1E88F3101CC384000C4DF5 /* ScriptArray.cpp */; };
                7A1E88F6101CC384000C4DF5 /* ScriptArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A1E88F4101CC384000C4DF5 /* ScriptArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7A24587B1021EAF4000A00AA /* InspectorDOMAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A2458791021EAF4000A00AA /* InspectorDOMAgent.cpp */; };
-               7A24587C1021EAF4000A00AA /* InspectorDOMAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A24587A1021EAF4000A00AA /* InspectorDOMAgent.h */; };
+               7A24587C1021EAF4000A00AA /* InspectorDOMAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A24587A1021EAF4000A00AA /* InspectorDOMAgent.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7A674BDB0F9EBF4E006CF099 /* PageGroupLoadDeferrer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A674BD90F9EBF4E006CF099 /* PageGroupLoadDeferrer.cpp */; };
                7A674BDC0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A674BDA0F9EBF4E006CF099 /* PageGroupLoadDeferrer.h */; };
                7A74ECBA101839A600BF939E /* InspectorBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A74ECB8101839A500BF939E /* InspectorBackend.cpp */; };
index 1c934c74348400cedf2b06113291a9ce87dc85d4..13f542e302fba2ea848ca96bad915b681367e3cd 100644 (file)
@@ -220,11 +220,6 @@ private:
     HashSet<DOMWrapperWorld*>::iterator m_end;
 };
 
-DOMWrapperWorld* currentWorld(JSC::ExecState* exec)
-{
-    return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world();
-}
-
 DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData)
 {
     JSGlobalData::ClientData* clientData = globalData.clientData;
@@ -556,11 +551,6 @@ void markDOMNodeWrapper(MarkStack& markStack, Document* document, Node* node)
     }
 }
 
-static inline JSStringCache& jsStringCache(ExecState* exec)
-{
-    return currentWorld(exec)->m_stringCache;
-}
-
 static void stringWrapperDestroyed(JSString* str, void* context)
 {
     StringImpl* cacheKey = static_cast<StringImpl*>(context);
@@ -583,19 +573,8 @@ static void stringWrapperDestroyed(JSString* str, void* context)
     cacheKey->deref();
 }
 
-JSValue jsString(ExecState* exec, const String& s)
+JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl)
 {
-    StringImpl* stringImpl = s.impl();
-    if (!stringImpl || !stringImpl->length())
-        return jsEmptyString(exec);
-
-    if (stringImpl->length() == 1 && stringImpl->characters()[0] <= 0xFF)
-        return jsString(exec, stringImpl->ustring());
-
-    JSStringCache& stringCache = jsStringCache(exec);
-    if (JSString* wrapper = stringCache.get(stringImpl))
-        return wrapper;
-
     // If there is a stale entry, we have to explicitly remove it to avoid
     // problems down the line.
     if (JSString* wrapper = stringCache.uncheckedGet(stringImpl))
index e20a2320a559d364b29ece01abda6479705fdaed..abacce2a15342869b102c0afc1d0aca80061dabe 100644 (file)
@@ -346,6 +346,7 @@ namespace WebCore {
     void setDOMException(JSC::ExecState*, ExceptionCode);
 
     JSC::JSValue jsString(JSC::ExecState*, const String&); // empty if the string is null
+    JSC::JSValue jsStringSlowCase(JSC::ExecState*, JSStringCache&, StringImpl*);
     JSC::JSValue jsString(JSC::ExecState*, const KURL&); // empty if the URL is null
     inline JSC::JSValue jsString(JSC::ExecState* exec, const AtomicString& s)
     { 
@@ -415,6 +416,27 @@ namespace WebCore {
     bool processingUserGesture(JSC::ExecState*);
     KURL completeURL(JSC::ExecState*, const String& relativeURL);
 
+    inline DOMWrapperWorld* currentWorld(JSC::ExecState* exec)
+    {
+        return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world();
+    }
+    
+    inline JSC::JSValue jsString(JSC::ExecState* exec, const String& s)
+    {
+        StringImpl* stringImpl = s.impl();
+        if (!stringImpl || !stringImpl->length())
+            return jsEmptyString(exec);
+
+        if (stringImpl->length() == 1 && stringImpl->characters()[0] <= 0xFF)
+            return jsString(exec, stringImpl->ustring());
+
+        JSStringCache& stringCache = currentWorld(exec)->m_stringCache;
+        if (JSC::JSString* wrapper = stringCache.get(stringImpl))
+            return wrapper;
+
+        return jsStringSlowCase(exec, stringCache, stringImpl);
+    }
+
 } // namespace WebCore
 
 #endif // JSDOMBinding_h
index 4dd6e45526b0e0af3f162cb5299ba8972db391fd..6e3be84e2e47dfd861429b823853a280e1b6dc46 100644 (file)
@@ -322,7 +322,7 @@ static bool disableRangeMutation(Page* page)
 
 static HashSet<Document*>* documentsThatNeedStyleRecalc = 0;
 
-Document::Document(Frame* frame, bool isXHTML)
+Document::Document(Frame* frame, bool isXHTML, bool isHTML)
     : ContainerNode(0)
     , m_domtree_version(0)
     , m_styleSheets(StyleSheetList::create(this))
@@ -357,6 +357,7 @@ Document::Document(Frame* frame, bool isXHTML)
     , m_inPageCache(false)
     , m_useSecureKeyboardEntryWhenActive(false)
     , m_isXHTML(isXHTML)
+    , m_isHTML(isHTML)
     , m_numNodeListCaches(0)
 #if USE(JSC)
     , m_normalWorldWrapperCache(0)
index 4d17e0b8f8461318547608e789b6e8267a451e13..7ebddf7d41a6ee70d126757f0c1c11503c892eb0 100644 (file)
@@ -32,6 +32,7 @@
 #include "CollectionCache.h"
 #include "CollectionType.h"
 #include "Color.h"
+#include "Document.h"
 #include "DocumentMarker.h"
 #include "ScriptExecutionContext.h"
 #include "Timer.h"
@@ -190,11 +191,11 @@ class Document : public ContainerNode, public ScriptExecutionContext {
 public:
     static PassRefPtr<Document> create(Frame* frame)
     {
-        return adoptRef(new Document(frame, false));
+        return adoptRef(new Document(frame, false, false));
     }
     static PassRefPtr<Document> createXHTML(Frame* frame)
     {
-        return adoptRef(new Document(frame, true));
+        return adoptRef(new Document(frame, true, false));
     }
     virtual ~Document();
 
@@ -365,7 +366,7 @@ public:
     CollectionCache* nameCollectionInfo(CollectionType, const AtomicString& name);
 
     // Other methods (not part of DOM)
-    virtual bool isHTMLDocument() const { return false; }
+    bool isHTMLDocument() const { return m_isHTML; }
     virtual bool isImageDocument() const { return false; }
 #if ENABLE(SVG)
     virtual bool isSVGDocument() const { return false; }
@@ -942,7 +943,7 @@ public:
 #endif
 
 protected:
-    Document(Frame*, bool isXHTML);
+    Document(Frame*, bool isXHTML, bool isHTML);
 
     void setStyleSelector(CSSStyleSelector* styleSelector) { m_styleSelector = styleSelector; }
 
@@ -1184,6 +1185,7 @@ private:
     bool m_useSecureKeyboardEntryWhenActive;
 
     bool m_isXHTML;
+    bool m_isHTML;
 
     unsigned m_numNodeListCaches;
 
index f115ff63bf378cd565ed2ce265724647b7e5abef..234bec4e25520bf8b7d418dbda0d77dc18715fa7 100644 (file)
@@ -160,21 +160,6 @@ NamedNodeMap* Element::attributes() const
     return attributes(false);
 }
 
-NamedNodeMap* Element::attributes(bool readonly) const
-{
-    if (!m_isStyleAttributeValid)
-        updateStyleAttribute();
-
-#if ENABLE(SVG)
-    if (!m_areSVGAttributesValid)
-        updateAnimatedSVGAttribute(String());
-#endif
-
-    if (!readonly && !namedAttrMap)
-        createAttributeMap();
-    return namedAttrMap.get();
-}
-
 Node::NodeType Element::nodeType() const
 {
     return ELEMENT_NODE;
@@ -1092,21 +1077,6 @@ String Element::openTagStartToString() const
     return result;
 }
 
-void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
-{
-    if (!inDocument())
-        return;
-
-    if (oldId == newId)
-        return;
-
-    Document* doc = document();
-    if (!oldId.isEmpty())
-        doc->removeElementById(oldId, this);
-    if (!newId.isEmpty())
-        doc->addElementById(newId, this);
-}
-
 #ifndef NDEBUG
 void Element::formatForDebugger(char* buffer, unsigned length) const
 {
index 9670eb1c00c2eb60b9f42cdc73ecfa74815f9714..1f8253827d4163d938fa80bc500b55522b61102c 100644 (file)
@@ -26,6 +26,7 @@
 #define Element_h
 
 #include "ContainerNode.h"
+#include "Document.h"
 #include "HTMLNames.h"
 #include "MappedAttributeEntry.h"
 #include "QualifiedName.h"
@@ -349,6 +350,36 @@ inline const QualifiedName& Element::idAttributeName() const
     return hasRareData() ? rareIDAttributeName() : HTMLNames::idAttr;
 }
 
+inline NamedNodeMap* Element::attributes(bool readonly) const
+{
+    if (!m_isStyleAttributeValid)
+        updateStyleAttribute();
+
+#if ENABLE(SVG)
+    if (!m_areSVGAttributesValid)
+        updateAnimatedSVGAttribute(String());
+#endif
+
+    if (!readonly && !namedAttrMap)
+        createAttributeMap();
+    return namedAttrMap.get();
+}
+
+inline void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
+{
+    if (!inDocument())
+        return;
+
+    if (oldId == newId)
+        return;
+
+    Document* doc = document();
+    if (!oldId.isEmpty())
+        doc->removeElementById(oldId, this);
+    if (!newId.isEmpty())
+        doc->addElementById(newId, this);
+}
+
 } //namespace
 
 #endif
index 24d4ef57116a99b2a3e1db96c3df4981a9005c4e..d8a6ba8ad9d45d2da0658fa70a9886519b4f3326 100644 (file)
@@ -172,52 +172,27 @@ PassRefPtr<Node> NamedNodeMap::item(unsigned index) const
     return m_attributes[index]->createAttrIfNeeded(m_element);
 }
 
-// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
-// can tune the behaviour (hasAttribute is case sensitive whereas getAttribute is not).
-Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const
+Attribute* NamedNodeMap::getAttributeItemSlowCase(const String& name, bool shouldIgnoreAttributeCase) const
 {
     unsigned len = length();
-    bool doSlowCheck = shouldIgnoreAttributeCase;
-    
-    // Optimize for the case where the attribute exists and its name exactly matches.
+
+    // Continue to checking case-insensitively and/or full namespaced names if necessary:
     for (unsigned i = 0; i < len; ++i) {
         const QualifiedName& attrName = m_attributes[i]->name();
         if (!attrName.hasPrefix()) {
-            if (name == attrName.localName())
+            if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName()))
+                return m_attributes[i].get();
+        } else {
+            // FIXME: Would be faster to do this comparison without calling toString, which
+            // generates a temporary string by concatenation. But this branch is only reached
+            // if the attribute name has a prefix, which is rare in HTML.
+            if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase))
                 return m_attributes[i].get();
-        } else
-            doSlowCheck = true;
-    }
-    
-    // Continue to checking case-insensitively and/or full namespaced names if necessary:
-    if (doSlowCheck) {
-        for (unsigned i = 0; i < len; ++i) {
-            const QualifiedName& attrName = m_attributes[i]->name();
-            if (!attrName.hasPrefix()) {
-                if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attrName.localName()))
-                    return m_attributes[i].get();
-            } else {
-                // FIXME: Would be faster to do this comparison without calling toString, which
-                // generates a temporary string by concatenation. But this branch is only reached
-                // if the attribute name has a prefix, which is rare in HTML.
-                if (equalPossiblyIgnoringCase(name, attrName.toString(), shouldIgnoreAttributeCase))
-                    return m_attributes[i].get();
-            }
         }
     }
     return 0;
 }
 
-Attribute* NamedNodeMap::getAttributeItem(const QualifiedName& name) const
-{
-    unsigned len = length();
-    for (unsigned i = 0; i < len; ++i) {
-        if (m_attributes[i]->name().matches(name))
-            return m_attributes[i].get();
-    }
-    return 0;
-}
-
 void NamedNodeMap::clearAttributes()
 {
     detachAttributesFromElement();
index 759900b71942d21f68ddded00f007ba8bf1e59af..d5136b5512e1f066676729554cdf7c2e9a1440f5 100644 (file)
@@ -103,12 +103,45 @@ private:
     void detachAttributesFromElement();
     void detachFromElement();
     Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const;
+    Attribute* getAttributeItemSlowCase(const String& name, bool shouldIgnoreAttributeCase) const;
 
     Element* m_element;
     Vector<RefPtr<Attribute> > m_attributes;
     AtomicString m_id;
 };
 
+inline Attribute* NamedNodeMap::getAttributeItem(const QualifiedName& name) const
+{
+    unsigned len = length();
+    for (unsigned i = 0; i < len; ++i) {
+        if (m_attributes[i]->name().matches(name))
+            return m_attributes[i].get();
+    }
+    return 0;
+}
+
+// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
+// can tune the behaviour (hasAttribute is case sensitive whereas getAttribute is not).
+inline Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const
+{
+    unsigned len = length();
+    bool doSlowCheck = shouldIgnoreAttributeCase;
+    
+    // Optimize for the case where the attribute exists and its name exactly matches.
+    for (unsigned i = 0; i < len; ++i) {
+        const QualifiedName& attrName = m_attributes[i]->name();
+        if (!attrName.hasPrefix()) {
+            if (name == attrName.localName())
+                return m_attributes[i].get();
+        } else
+            doSlowCheck = true;
+    }
+
+    if (doSlowCheck)
+        return getAttributeItemSlowCase(name, shouldIgnoreAttributeCase);
+    return 0;
+}
+
 } //namespace
 
 #undef id
index 0d1cb19bac238a6c567f7a3197db6abf991752f4..5d1db312133292276c0fc05956228d8d07c6ec44 100644 (file)
@@ -80,7 +80,7 @@ namespace WebCore {
 using namespace HTMLNames;
 
 HTMLDocument::HTMLDocument(Frame* frame)
-    : Document(frame, false)
+    : Document(frame, false, true)
 {
     clearXMLVersion();
     setParseMode(Compat);
index 4b14d0c9e26000f5cb6fd4e882d1ea85c9ac9645..6d89abbbeb9dfa92f3ba9c9a9889dc80077c79a5 100644 (file)
@@ -87,7 +87,6 @@ private:
 
     virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
 
-    virtual bool isHTMLDocument() const { return true; }
     virtual bool isFrameSet() const;
     virtual Tokenizer* createTokenizer();
     virtual void determineParseMode();
index ccd9be113b39d385e6dc7e6595019c836244c855..c84a4150ba2f6a6c141b59babf0ede1522ea298d 100644 (file)
@@ -1874,24 +1874,6 @@ void InspectorController::deleteCookie(const String& cookieName, const String& d
     }
 }
 
-void InspectorController::didInsertDOMNode(Node* node)
-{
-    if (m_domAgent)
-        m_domAgent->didInsertDOMNode(node);
-}
-
-void InspectorController::didRemoveDOMNode(Node* node)
-{
-    if (m_domAgent)
-        m_domAgent->didRemoveDOMNode(node);
-}
-
-void InspectorController::didModifyDOMAttr(Element* element)
-{
-    if (m_domAgent)
-        m_domAgent->didModifyDOMAttr(element);
-}
-
 }  // namespace WebCore
     
 #endif // ENABLE(INSPECTOR)
index 3eeeafbab59b694fc3e39c338ecad511ad124ff8..85e40dff089a69c8b40983966249cb5fb995d297 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "Console.h"
 #include "Cookie.h"
+#include "InspectorDOMAgent.h"
 #include "PlatformString.h"
 #include "ScriptArray.h"
 #include "ScriptObject.h"
@@ -66,7 +67,6 @@ class HitTestResult;
 class InjectedScriptHost;
 class InspectorBackend;
 class InspectorClient;
-class InspectorDOMAgent;
 class InspectorFrontend;
 class InspectorFrontendHost;
 class InspectorTimelineAgent;
@@ -370,6 +370,24 @@ private:
 #endif
 };
 
+inline void InspectorController::didInsertDOMNode(Node* node)
+{
+    if (m_domAgent)
+        m_domAgent->didInsertDOMNode(node);
+}
+
+inline void InspectorController::didRemoveDOMNode(Node* node)
+{
+    if (m_domAgent)
+        m_domAgent->didRemoveDOMNode(node);
+}
+
+inline void InspectorController::didModifyDOMAttr(Element* element)
+{
+    if (m_domAgent)
+        m_domAgent->didModifyDOMAttr(element);
+}
+
 } // namespace WebCore
 
 #endif // !defined(InspectorController_h)
index a7592661f959e3396d2536871685363af9bd2a50..5b76a9c70433160c13a9e9310aee946dd2b72f34 100644 (file)
@@ -40,7 +40,7 @@ public:
     virtual void attach();
 
 private:
-    PlaceholderDocument(Frame* frame) : Document(frame, false) { }
+    PlaceholderDocument(Frame* frame) : Document(frame, false, false) { }
 };
 
 } // namespace WebCore
index 26a97286dbc1ab87d2a9d00861216cb36b215565..5c3c2944cb719afb9f445cbfe33bdbe8a1bacd1f 100644 (file)
@@ -48,24 +48,11 @@ using namespace WTF;
 
 namespace WebCore {
 
-ThreadGlobalData& threadGlobalData()
-{
-    // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary.
-    // We need to check for e.g. database objects manipulating strings on secondary threads.
 #if ENABLE(WORKERS)
-    // ThreadGlobalData is used on main thread before it could possibly be used on secondary ones, so there is no need for synchronization here.
-    static ThreadSpecific<ThreadGlobalData>* threadGlobalData = new ThreadSpecific<ThreadGlobalData>;
-    return **threadGlobalData;
+ThreadSpecific<ThreadGlobalData>* ThreadGlobalData::staticData;
 #else
-    static ThreadGlobalData* staticData;
-    if (!staticData) {
-        staticData = static_cast<ThreadGlobalData*>(fastMalloc(sizeof(ThreadGlobalData)));
-        // ThreadGlobalData constructor indirectly uses staticData, so we need to set up the memory before invoking it.
-        new (staticData) ThreadGlobalData;
-    }
-    return *staticData;
+ThreadGlobalData* ThreadGlobalData::staticData;
 #endif
-}
 
 ThreadGlobalData::ThreadGlobalData()
     : m_emptyString(new StringImpl)
@@ -92,7 +79,6 @@ ThreadGlobalData::~ThreadGlobalData()
 #if USE(ICU_UNICODE)
     delete m_cachedConverterICU;
 #endif
-
     delete m_eventNames;
     delete m_atomicStringTable;
     delete m_threadTimers;
index 68f5ec04a5109fa8293905253dfd8029190725a0..9f7865d75a97587142504eaf323ef37005967b68 100644 (file)
 #define ThreadGlobalData_h
 
 #include "StringHash.h"
+#include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
 
+#if ENABLE(WORKERS)
+#include <wtf/ThreadSpecific.h>
+#include <wtf/Threading.h>
+using WTF::ThreadSpecific;
+#endif
+
 namespace WebCore {
 
     class EventNames;
@@ -73,10 +80,35 @@ namespace WebCore {
 #if PLATFORM(MAC)
         TECConverterWrapper* m_cachedConverterTEC;
 #endif
+
+#if ENABLE(WORKERS)
+        static ThreadSpecific<ThreadGlobalData>* staticData;
+#else
+        static ThreadGlobalData* staticData;
+#endif
+        friend ThreadGlobalData& threadGlobalData();
     };
 
-    ThreadGlobalData& threadGlobalData();
+inline ThreadGlobalData& threadGlobalData() 
+{
+    // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary.
+    // We need to check for e.g. database objects manipulating strings on secondary threads.
 
+#if ENABLE(WORKERS)
+    // ThreadGlobalData is used on main thread before it could possibly be used on secondary ones, so there is no need for synchronization here.
+    if (!ThreadGlobalData::staticData)
+        ThreadGlobalData::staticData = new ThreadSpecific<ThreadGlobalData>;
+    return **ThreadGlobalData::staticData;
+#else
+    if (!ThreadGlobalData::staticData) {
+        ThreadGlobalData::staticData = static_cast<ThreadGlobalData*>(fastMalloc(sizeof(ThreadGlobalData)));
+        // ThreadGlobalData constructor indirectly uses staticData, so we need to set up the memory before invoking it.
+        new (ThreadGlobalData::staticData) ThreadGlobalData;
+    }
+    return *ThreadGlobalData::staticData;
+#endif
+}
+    
 } // namespace WebCore
 
 #endif // ThreadGlobalData_h
index 539846c8c51b40f40e310dc6e616aeb39958befa..3f4e334f905a7072c355f0dd90897a54ec97ee23 100644 (file)
@@ -196,13 +196,6 @@ void TimerBase::stop()
     ASSERT(!inHeap());
 }
 
-bool TimerBase::isActive() const
-{
-    ASSERT(m_thread == currentThread());
-
-    return m_nextFireTime;
-}
-
 double TimerBase::nextFireInterval() const
 {
     ASSERT(isActive());
index 9221df07d568703c8d8d2bba70473640d45271f9..c4443da4937c1b7868aaa0236e8332b3208b22ff 100644 (file)
@@ -101,6 +101,12 @@ private:
     TimerFiredFunction m_function;
 };
 
+inline bool TimerBase::isActive() const
+{
+    ASSERT(m_thread == currentThread());
+    return m_nextFireTime;
+}
+
 }
 
 #endif
index fe8ab80429075cb6108a5a21c6da1ff139d9c0f6..2264a112b0962db20774a8aaa738caf82505a86d 100644 (file)
@@ -36,7 +36,7 @@
 namespace WebCore {
 
 SVGDocument::SVGDocument(Frame* frame)
-    : Document(frame, false)
+    : Document(frame, false, false)
 {
 }