2011-04-14 Geoffrey Garen <ggaren@apple.com>
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Apr 2011 17:44:34 +0000 (17:44 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Apr 2011 17:44:34 +0000 (17:44 +0000)
        Reviewed by Oliver Hunt.

        Complicated hash table is complicated
        https://bugs.webkit.org/show_bug.cgi?id=58631

        Now that we use the opaque roots system to track node wrapper lifetime,
        we can remove a lot of complicated hash-tablery that used to do the same.

        Now normal world node wrappers are just set as direct properties of
        ScriptWrappable, while isolated world node wrappers and other DOM object
        wrappers are stored in a shared, per-world hash table.

        In addition to reducing complexity, this makes DOM wrapper allocation
        1.6X faster (tested with scratch-gc-dom3.html), and it reduces the memory
        footprint of normal world wrappers by ~2/3, and isolated world wrappers
        by ~1/3.

        * WebCore.exp.in: Paying the patch tithe.

        * bindings/js/DOMWrapperWorld.cpp:
        (WebCore::DOMWrapperWorld::~DOMWrapperWorld):
        (WebCore::DOMWrapperWorld::clearWrappers): No more per-document hash tables.

        (WebCore::JSNodeHandleOwner::finalize): Changed to call a helper function,
        so the code to destroy a wrapper can live next to the code to create one.

        * bindings/js/DOMWrapperWorld.h: No more per-document hash tables.

        * bindings/js/JSDOMBinding.cpp:
        (WebCore::uncacheDOMObjectWrapper):
        * bindings/js/JSDOMBinding.h:
        (WebCore::createDOMNodeWrapper):
        (WebCore::getDOMNodeWrapper): No more per-document hash tables.
        Added uncacheDOMObjectWrapper to be symmetrical with cacheDOMObjectWrapper.

        * bindings/js/JSDocumentCustom.cpp:
        (WebCore::toJS):
        * bindings/js/JSElementCustom.cpp:
        (WebCore::toJSNewlyCreated):
        * bindings/js/JSNodeCustom.cpp:
        (WebCore::createWrapperInline): Ditto.

        * bindings/js/JSNodeCustom.h:
        (WebCore::getCachedDOMNodeWrapper):
        (WebCore::cacheDOMNodeWrapper):
        (WebCore::uncacheDOMNodeWrapper):
        (WebCore::toJS): Implemented the scheme described above.

        * bindings/js/ScriptWrappable.h:
        (WebCore::ScriptWrappable::wrapper):
        (WebCore::ScriptWrappable::setWrapper):
        (WebCore::ScriptWrappable::clearWrapper): ScriptWrappable needs a handle
        owner now, since we don't have an extra handle living in a hash table
        to maintain ownership for us.

        * dom/Document.cpp:
        (WebCore::Document::Document):
        (WebCore::Document::~Document):
        * dom/Document.h:
        * dom/Node.cpp:
        (WebCore::Node::setDocument): No more per-document hash tables.

        * html/HTMLCanvasElement.cpp:
        (WebCore::HTMLCanvasElement::createImageBuffer): Removed call to
        hasCachedDOMNodeWrapperUnchecked because that was the old way of doing
        things, and I was in the mood for getting rid of the old way. It's
        debatable whether the check was ever a good idea. Even when a <canvas>
        doesn't have a direct JS wrapper, other JS references can still keep
        the <canvas> alive. So, it's probably best always to report extra cost.

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

15 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/bindings/js/DOMWrapperWorld.cpp
Source/WebCore/bindings/js/DOMWrapperWorld.h
Source/WebCore/bindings/js/JSDOMBinding.cpp
Source/WebCore/bindings/js/JSDOMBinding.h
Source/WebCore/bindings/js/JSDocumentCustom.cpp
Source/WebCore/bindings/js/JSElementCustom.cpp
Source/WebCore/bindings/js/JSNodeCustom.cpp
Source/WebCore/bindings/js/JSNodeCustom.h
Source/WebCore/bindings/js/ScriptWrappable.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/Node.cpp
Source/WebCore/html/HTMLCanvasElement.cpp

index 54fe1e6..abe9886 100644 (file)
@@ -1,3 +1,75 @@
+2011-04-14  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Complicated hash table is complicated
+        https://bugs.webkit.org/show_bug.cgi?id=58631
+        
+        Now that we use the opaque roots system to track node wrapper lifetime,
+        we can remove a lot of complicated hash-tablery that used to do the same.
+        
+        Now normal world node wrappers are just set as direct properties of
+        ScriptWrappable, while isolated world node wrappers and other DOM object
+        wrappers are stored in a shared, per-world hash table.
+
+        In addition to reducing complexity, this makes DOM wrapper allocation
+        1.6X faster (tested with scratch-gc-dom3.html), and it reduces the memory
+        footprint of normal world wrappers by ~2/3, and isolated world wrappers
+        by ~1/3.
+
+        * WebCore.exp.in: Paying the patch tithe.
+
+        * bindings/js/DOMWrapperWorld.cpp:
+        (WebCore::DOMWrapperWorld::~DOMWrapperWorld):
+        (WebCore::DOMWrapperWorld::clearWrappers): No more per-document hash tables.
+
+        (WebCore::JSNodeHandleOwner::finalize): Changed to call a helper function,
+        so the code to destroy a wrapper can live next to the code to create one.
+
+        * bindings/js/DOMWrapperWorld.h: No more per-document hash tables.
+
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::uncacheDOMObjectWrapper):
+        * bindings/js/JSDOMBinding.h:
+        (WebCore::createDOMNodeWrapper):
+        (WebCore::getDOMNodeWrapper): No more per-document hash tables.
+        Added uncacheDOMObjectWrapper to be symmetrical with cacheDOMObjectWrapper.
+
+        * bindings/js/JSDocumentCustom.cpp:
+        (WebCore::toJS):
+        * bindings/js/JSElementCustom.cpp:
+        (WebCore::toJSNewlyCreated):
+        * bindings/js/JSNodeCustom.cpp:
+        (WebCore::createWrapperInline): Ditto.
+
+        * bindings/js/JSNodeCustom.h:
+        (WebCore::getCachedDOMNodeWrapper):
+        (WebCore::cacheDOMNodeWrapper):
+        (WebCore::uncacheDOMNodeWrapper):
+        (WebCore::toJS): Implemented the scheme described above.
+
+        * bindings/js/ScriptWrappable.h:
+        (WebCore::ScriptWrappable::wrapper):
+        (WebCore::ScriptWrappable::setWrapper):
+        (WebCore::ScriptWrappable::clearWrapper): ScriptWrappable needs a handle
+        owner now, since we don't have an extra handle living in a hash table
+        to maintain ownership for us.
+
+        * dom/Document.cpp:
+        (WebCore::Document::Document):
+        (WebCore::Document::~Document):
+        * dom/Document.h:
+        * dom/Node.cpp:
+        (WebCore::Node::setDocument): No more per-document hash tables.
+
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::createImageBuffer): Removed call to
+        hasCachedDOMNodeWrapperUnchecked because that was the old way of doing
+        things, and I was in the mood for getting rid of the old way. It's
+        debatable whether the check was ever a good idea. Even when a <canvas>
+        doesn't have a direct JS wrapper, other JS references can still keep
+        the <canvas> alive. So, it's probably best always to report extra cost.
+
 2011-04-15  Vsevolod Vlasov  <vsevik@chromium.org>
 
         Reviewed by Pavel Feldman.
index 41ed3fa..fd4da6e 100644 (file)
@@ -297,8 +297,8 @@ __ZN7WebCore12SharedBufferD1Ev
 __ZN7WebCore12SpellChecker8didCheckEiRKN3WTF6VectorINS_18TextCheckingResultELm0EEE
 __ZN7WebCore12TextEncodingC1ERKN3WTF6StringE
 __ZN7WebCore12TextIterator11rangeLengthEPKNS_5RangeEb
-__ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_7ElementEiib
 __ZN7WebCore12TextIterator26locationAndLengthFromRangeEPKNS_5RangeERmS4_
+__ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_7ElementEiib
 __ZN7WebCore12TextIterator7advanceEv
 __ZN7WebCore12TextIterator8subrangeEPNS_5RangeEii
 __ZN7WebCore12TextIteratorC1EPKNS_5RangeENS_20TextIteratorBehaviorE
@@ -350,6 +350,7 @@ __ZN7WebCore14DocumentLoaderC2ERKNS_15ResourceRequestERKNS_14SubstituteDataE
 __ZN7WebCore14DocumentLoaderD2Ev
 __ZN7WebCore14DocumentWriter11setEncodingERKN3WTF6StringEb
 __ZN7WebCore14ResourceHandle12releaseProxyEv
+__ZN7WebCore25getCachedDOMObjectWrapperEPN3JSC9ExecStateEPv
 __ZN7WebCore14ResourceHandle20forceContentSniffingEv
 __ZN7WebCore14ResourceLoader14cancelledErrorEv
 __ZN7WebCore14ResourceLoader19setShouldBufferDataEb
@@ -812,7 +813,6 @@ __ZN7WebCore8Document13svgExtensionsEv
 __ZN7WebCore8Document14setFocusedNodeEN3WTF10PassRefPtrINS_4NodeEEE
 __ZN7WebCore8Document16isPageBoxVisibleEi
 __ZN7WebCore8Document17getFocusableNodesERN3WTF6VectorINS1_6RefPtrINS_4NodeEEELm0EEE
-__ZN7WebCore8Document18createWrapperCacheEPNS_15DOMWrapperWorldE
 __ZN7WebCore8Document19accessSVGExtensionsEv
 __ZN7WebCore8Document20styleSelectorChangedENS_23StyleSelectorUpdateFlagE
 __ZN7WebCore8Document22createDocumentFragmentEv
index d38def2..b33443d 100644 (file)
@@ -161,26 +161,12 @@ DOMWrapperWorld::~DOMWrapperWorld()
     JSGlobalData::ClientData* clientData = m_globalData->clientData;
     ASSERT(clientData);
     static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this);
-
-    // These items are created lazily.
-    while (!m_documentsWithWrapperCaches.isEmpty())
-        (*m_documentsWithWrapperCaches.begin())->destroyWrapperCache(this);
-
-    while (!m_scriptControllersWithWindowShells.isEmpty())
-        (*m_scriptControllersWithWindowShells.begin())->destroyWindowShell(this);
 }
 
 void DOMWrapperWorld::clearWrappers()
 {
     m_wrappers.clear();
     m_stringCache.clear();
-
-    // These items are created lazily.
-    while (!m_documentsWithWrapperCaches.isEmpty())
-        (*m_documentsWithWrapperCaches.begin())->destroyWrapperCache(this);
-
-    while (!m_scriptControllersWithWindowShells.isEmpty())
-        (*m_scriptControllersWithWindowShells.begin())->destroyWindowShell(this);
 }
 
 DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData)
@@ -206,10 +192,7 @@ bool JSNodeHandleOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> han
 void JSNodeHandleOwner::finalize(JSC::Handle<JSC::Unknown> handle, void*)
 {
     JSNode* jsNode = static_cast<JSNode*>(handle.get().asCell());
-    Node* node = jsNode->impl();
-    ASSERT(node->document());
-    ASSERT(node->document()->getWrapperCache(m_world)->find(node)->second == jsNode);
-    node->document()->getWrapperCache(m_world)->remove(node);
+    uncacheDOMNodeWrapper(m_world, jsNode->impl(), jsNode);
 }
 
 bool DOMObjectHandleOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void*, JSC::MarkStack&)
index 8f0b506..ea87cc5 100644 (file)
 #ifndef DOMWrapperWorld_h
 #define DOMWrapperWorld_h
 
-#include "Document.h"
 #include "JSDOMGlobalObject.h"
-#include "JSDOMWrapper.h"
 #include <runtime/WeakGCMap.h>
 #include <wtf/Forward.h>
 
 namespace WebCore {
 
+class DOMObject;
 class ScriptController;
 
 typedef HashMap<void*, JSC::Weak<DOMObject> > DOMObjectWrapperMap;
@@ -76,9 +75,6 @@ public:
     // Free as much memory held onto by this world as possible.
     void clearWrappers();
 
-    void didCreateWrapperCache(Document* document) { m_documentsWithWrapperCaches.add(document); }
-    void didDestroyWrapperCache(Document* document) { m_documentsWithWrapperCaches.remove(document); }
-
     void didCreateWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.add(scriptController); }
     void didDestroyWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.remove(scriptController); }
 
@@ -97,7 +93,6 @@ protected:
 
 private:
     JSC::JSGlobalData* m_globalData;
-    HashSet<Document*> m_documentsWithWrapperCaches;
     HashSet<ScriptController*> m_scriptControllersWithWindowShells;
     bool m_isNormal;
     JSNodeHandleOwner m_jsNodeHandleOwner;
@@ -114,19 +109,6 @@ inline DOMWrapperWorld* currentWorld(JSC::ExecState* exec)
     return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world();
 }
 
-// From Document.h
-
-inline Document::JSWrapperCache* Document::getWrapperCache(DOMWrapperWorld* world)
-{
-    if (world->isNormal()) {
-        if (Document::JSWrapperCache* wrapperCache = m_normalWorldWrapperCache)
-            return wrapperCache;
-        ASSERT(!m_wrapperCacheMap.contains(world));
-    } else if (Document::JSWrapperCache* wrapperCache = m_wrapperCacheMap.get(world))
-        return wrapperCache;
-    return createWrapperCache(world);
-}
-
 } // namespace WebCore
 
 #endif // DOMWrapperWorld_h
index 661e211..16ed277 100644 (file)
@@ -94,9 +94,6 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-typedef Document::JSWrapperCache JSWrapperCache;
-typedef Document::JSWrapperCacheMap JSWrapperCacheMap;
-
 class JSGlobalDataWorldIterator {
 public:
     JSGlobalDataWorldIterator(JSGlobalData* globalData)
@@ -167,31 +164,10 @@ void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject*
     world->m_wrappers.set(objectHandle, Weak<DOMObject>(*world->globalData(), wrapper, world->domObjectHandleOwner()));
 }
 
-bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node)
-{
-    if (!document)
-        return hasCachedDOMObjectWrapperUnchecked(JSDOMWindow::commonJSGlobalData(), node);
-
-    JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
-    for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
-        if (iter->second->get(node))
-            return true;
-    }
-    return false;
-}
-
-void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper)
+void uncacheDOMObjectWrapper(DOMWrapperWorld* world, void* objectHandle, DOMObject* wrapper)
 {
-    ASSERT(wrapper);
-    if (!document)
-        cacheDOMObjectWrapper(exec, node, wrapper);
-    else
-        document->getWrapperCache(currentWorld(exec))->set(node, Weak<JSNode>(exec->globalData(), wrapper, currentWorld(exec)->jsNodeHandleOwner()));
-
-    if (currentWorld(exec)->isNormal()) {
-        node->setWrapper(exec->globalData(), wrapper);
-        ASSERT(node->wrapper() == (document ? document->getWrapperCache(currentWorld(exec))->get(node).get() : domObjectWrapperMapFor(exec).get(node).get()));
-    }
+    ASSERT_UNUSED(wrapper, world->m_wrappers.get(objectHandle) == wrapper);
+    world->m_wrappers.remove(objectHandle);
 }
 
 void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, ScriptExecutionContext* scriptExecutionContext)
@@ -218,44 +194,6 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData,
     }
 }
 
-typedef std::pair<JSNode*, DOMWrapperWorld*> WrapperAndWorld;
-typedef WTF::Vector<WrapperAndWorld, 8> WrapperSet;
-
-static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrapperSet)
-{
-    if (document) {
-        JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap();
-        for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) {
-            JSNode* wrapper = iter->second->take(node).get();
-            if (!wrapper)
-                continue;
-            wrapperSet.append(WrapperAndWorld(wrapper, iter->first));
-        }
-    } else {
-        for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) {
-            DOMWrapperWorld* world = *worldIter;
-            if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node).get()))
-                wrapperSet.append(WrapperAndWorld(wrapper, world));
-        }
-    }
-}
-
-void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocument)
-{
-    ASSERT(oldDocument != newDocument);
-
-    WrapperSet wrapperSet;
-    takeWrappers(node, oldDocument, wrapperSet);
-
-    for (unsigned i = 0; i < wrapperSet.size(); ++i) {
-        JSNode* wrapper = wrapperSet[i].first;
-        if (newDocument)
-            newDocument->getWrapperCache(wrapperSet[i].second)->set(node, Weak<JSNode>(*wrapperSet[i].second->globalData(), wrapper, wrapperSet[i].second->jsNodeHandleOwner()));
-        else
-            wrapperSet[i].second->m_wrappers.set(node, Weak<DOMObject>(*wrapperSet[i].second->globalData(), wrapper, wrapperSet[i].second->domObjectHandleOwner()));
-    }
-}
-
 void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object)
 {
     // FIXME: This could be changed to only mark wrappers that are "observable"
index 8d3ef01..9295aaa 100644 (file)
@@ -116,15 +116,15 @@ namespace WebCore {
     DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle);
     bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle);
     void cacheDOMObjectWrapper(JSC::ExecState*, void* objectHandle, DOMObject* wrapper);
+    void uncacheDOMObjectWrapper(DOMWrapperWorld*, void* objectHandle, DOMObject* wrapper);
 
-    JSNode* getCachedDOMNodeWrapper(JSC::ExecState*, Document*, Node*);
-    void cacheDOMNodeWrapper(JSC::ExecState*, Document*, Node*, JSNode* wrapper);
-    void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument);
-
+    JSNode* getCachedDOMNodeWrapper(JSC::ExecState*, Node*);
+    void cacheDOMNodeWrapper(JSC::ExecState*, Node*, JSNode* wrapper);
+    void uncacheDOMNodeWrapper(DOMWrapperWorld*, Node*, JSNode* wrapper);
+    
     void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*);
     void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object);
     bool hasCachedDOMObjectWrapperUnchecked(JSC::JSGlobalData*, void* objectHandle);
-    bool hasCachedDOMNodeWrapperUnchecked(Document*, Node*);
 
     JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
     JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
@@ -175,18 +175,18 @@ namespace WebCore {
     template<class WrapperClass, class DOMClass> inline JSNode* createDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
     {
         ASSERT(node);
-        ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node));
+        ASSERT(!getCachedDOMNodeWrapper(exec, node));
         WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, node);
         // FIXME: The entire function can be removed, once we fix caching.
         // This function is a one-off hack to make Nodes cache in the right global object.
-        cacheDOMNodeWrapper(exec, node->document(), node, wrapper);
+        cacheDOMNodeWrapper(exec, node, wrapper);
         return wrapper;
     }
     template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
     {
         if (!node)
             return JSC::jsNull();
-        if (JSC::JSCell* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node))
+        if (JSC::JSCell* wrapper = getCachedDOMNodeWrapper(exec, node))
             return wrapper;
         return createDOMNodeWrapper<WrapperClass>(exec, globalObject, node);
     }
index 7d1e5fa..1316566 100644 (file)
@@ -100,7 +100,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* documen
     if (!document)
         return jsNull();
 
-    DOMObject* wrapper = getCachedDOMNodeWrapper(exec, document, document);
+    DOMObject* wrapper = getCachedDOMNodeWrapper(exec, document);
     if (wrapper)
         return wrapper;
 
index 9ed3739..62ca04d 100644 (file)
@@ -71,7 +71,7 @@ JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Eleme
     if (!element)
         return jsNull();
 
-    ASSERT(!getCachedDOMNodeWrapper(exec, element->document(), element));
+    ASSERT(!getCachedDOMNodeWrapper(exec, element));
 
     JSNode* wrapper;        
     if (element->isHTMLElement())
index 4402500..b54869c 100644 (file)
@@ -130,7 +130,7 @@ void JSNode::markChildren(MarkStack& markStack)
 static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
 {
     ASSERT(node);
-    ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node));
+    ASSERT(!getCachedDOMNodeWrapper(exec, node));
     
     JSNode* wrapper;    
     switch (node->nodeType()) {
index 6e00769..c50716a 100644 (file)
 
 namespace WebCore {
 
-inline JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node)
+inline JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Node* node)
 {
-    if (currentWorld(exec)->isNormal()) {
-        ASSERT(node->wrapper() == (document ? document->getWrapperCache(currentWorld(exec))->get(node).get() : domObjectWrapperMapFor(exec).get(node).get()));
+    if (currentWorld(exec)->isNormal())
         return static_cast<JSNode*>(node->wrapper());
+    return static_cast<JSNode*>(getCachedDOMObjectWrapper(exec, node));
+}
+
+inline void cacheDOMNodeWrapper(JSC::ExecState* exec, Node* node, JSNode* wrapper)
+{
+    ASSERT(wrapper);
+
+    DOMWrapperWorld* world = currentWorld(exec);
+    if (world->isNormal()) {
+        node->setWrapper(*world->globalData(), wrapper, world->jsNodeHandleOwner());
+        return;
     }
+    cacheDOMObjectWrapper(exec, node, wrapper);
+}
 
-    if (document)
-        return document->getWrapperCache(currentWorld(exec))->get(node).get();
-    return static_cast<JSNode*>(domObjectWrapperMapFor(exec).get(node).get());
+inline void uncacheDOMNodeWrapper(DOMWrapperWorld* world, Node* node, JSNode* jsNode)
+{
+    if (world->isNormal()) {
+        node->clearWrapper();
+        return;
+    }
+    uncacheDOMObjectWrapper(world, node, jsNode);
 }
 
 JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Node*);
@@ -50,7 +66,7 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject,
     if (!node)
         return JSC::jsNull();
 
-    JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node);
+    JSNode* wrapper = getCachedDOMNodeWrapper(exec, node);
     if (wrapper)
         return wrapper;
 
index 1f522fc..1111b55 100644 (file)
@@ -38,18 +38,19 @@ namespace WebCore {
 
 class ScriptWrappable {
 public:
-    ScriptWrappable()
+    DOMObject* wrapper() const
     {
+        return m_wrapper.get();
     }
 
-    DOMObject* wrapper() const
+    void setWrapper(JSC::JSGlobalData& globalData, DOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner)
     {
-        return m_wrapper.get();
+        m_wrapper.set(globalData, wrapper, wrapperOwner);
     }
 
-    void setWrapper(JSC::JSGlobalData& globalData, DOMObject* wrapper)
+    void clearWrapper()
     {
-        m_wrapper.set(globalData, wrapper, 0);
+        m_wrapper.clear();
     }
 
 private:
index 10b2766..64082e3 100644 (file)
@@ -414,9 +414,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
     , m_isHTML(isHTML)
     , m_usesViewSourceStyles(false)
     , m_sawElementsInKnownNamespaces(false)
-#if USE(JSC)
-    , m_normalWorldWrapperCache(0)
-#endif
     , m_usingGeolocation(false)
     , m_eventQueue(EventQueue::create(this))
 #if ENABLE(WML)
@@ -522,10 +519,6 @@ Document::~Document()
 
     removeAllEventListeners();
 
-#if USE(JSC)
-    destroyAllWrapperCaches();
-#endif
-
     // Currently we believe that Document can never outlive the parser.
     // Although the Document may be replaced synchronously, DocumentParsers
     // generally keep at least one reference to an Element which would in turn
@@ -632,35 +625,6 @@ MediaQueryMatcher* Document::mediaQueryMatcher()
     return m_mediaQueryMatcher.get();
 }
 
-#if USE(JSC)
-Document::JSWrapperCache* Document::createWrapperCache(DOMWrapperWorld* world)
-{
-    JSWrapperCache* wrapperCache = new JSWrapperCache;
-    m_wrapperCacheMap.set(world, wrapperCache);
-    if (world->isNormal()) {
-        ASSERT(!m_normalWorldWrapperCache);
-        m_normalWorldWrapperCache = wrapperCache;
-    }
-    world->didCreateWrapperCache(this);
-    return wrapperCache;
-}
-
-void Document::destroyWrapperCache(DOMWrapperWorld* world)
-{
-    Document::JSWrapperCache* wrappers = wrapperCacheMap().take(world);
-    ASSERT(wrappers);
-    delete wrappers;
-    world->didDestroyWrapperCache(this);
-}
-
-void Document::destroyAllWrapperCaches()
-{
-    JSWrapperCacheMap& wrapperCacheMap = this->wrapperCacheMap();
-    while (!wrapperCacheMap.isEmpty())
-        destroyWrapperCache(wrapperCacheMap.begin()->first);
-}
-#endif
-
 void Document::setCompatibilityMode(CompatibilityMode mode)
 {
     if (m_compatibilityModeLocked || mode == m_compatibilityMode)
index d33b08c..4f3efda 100644 (file)
 #include <wtf/PassOwnPtr.h>
 #include <wtf/PassRefPtr.h>
 
-#if USE(JSC)
-#include <heap/Weak.h>
-#endif
-
 namespace WebCore {
 
 class AXObjectCache;
@@ -947,16 +943,6 @@ public:
     virtual void suspendScriptedAnimationControllerCallbacks();
     virtual void resumeScriptedAnimationControllerCallbacks();
 
-#if USE(JSC)
-    typedef HashMap<WebCore::Node*, JSC::Weak<JSNode> > JSWrapperCache;
-    typedef HashMap<DOMWrapperWorld*, JSWrapperCache*> JSWrapperCacheMap;
-    JSWrapperCacheMap& wrapperCacheMap() { return m_wrapperCacheMap; }
-    JSWrapperCache* getWrapperCache(DOMWrapperWorld* world);
-    JSWrapperCache* createWrapperCache(DOMWrapperWorld*);
-    void destroyWrapperCache(DOMWrapperWorld*);
-    void destroyAllWrapperCaches();
-#endif
-
     virtual void finishedParsing();
 
     bool inPageCache() const { return m_inPageCache; }
@@ -1363,11 +1349,6 @@ private:
     bool m_usesViewSourceStyles;
     bool m_sawElementsInKnownNamespaces;
 
-#if USE(JSC)
-    JSWrapperCacheMap m_wrapperCacheMap;
-    JSWrapperCache* m_normalWorldWrapperCache;
-#endif
-
     bool m_usingGeolocation;
     
     RefPtr<EventQueue> m_eventQueue;
index 38680a5..18c9d77 100644 (file)
@@ -448,10 +448,6 @@ void Node::setDocument(Document* document)
     willMoveToNewOwnerDocument();
     ASSERT(willMoveToNewOwnerDocumentWasCalled);
 
-#if USE(JSC)
-    updateDOMNodeDocument(this, m_document, document);
-#endif
-
     if (hasRareData() && rareData()->nodeLists()) {
         if (m_document)
             m_document->removeNodeListCache();
index 479d57a..19c0d08 100644 (file)
@@ -438,10 +438,8 @@ void HTMLCanvasElement::createImageBuffer() const
     m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQuality);
 
 #if USE(JSC)
-    if (hasCachedDOMNodeWrapperUnchecked(document(), const_cast<HTMLCanvasElement*>(this))) {
-        JSC::JSLock lock(JSC::SilenceAssertionsOnly);
-        scriptExecutionContext()->globalData()->heap.reportExtraMemoryCost(m_imageBuffer->dataSize());
-    }
+    JSC::JSLock lock(JSC::SilenceAssertionsOnly);
+    scriptExecutionContext()->globalData()->heap.reportExtraMemoryCost(m_imageBuffer->dataSize());
 #endif
 }