2010-02-24 Maciej Stachowiak <mjs@apple.com>
authormjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Feb 2010 04:07:37 +0000 (04:07 +0000)
committermjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Feb 2010 04:07:37 +0000 (04:07 +0000)
        Reviewed by Oliver Hunt.

        Cache JavaScript wrappers inline in DOM nodes
        https://bugs.webkit.org/show_bug.cgi?id=35226

        <rdar://problem/7664202>

        7.4% speedup on Dromaeo DOM Core tests.
        2.3% speedup on Hixie DOM Core tests.

        This fixes the following things from the last attempt:
        - Now builds in both debug and release and passes all tests
        - Properly use a WeakGCPtr, not just a raw pointer, in ScriptWrappable
        - Properly look in the appropriate per-document or per-world map
        - Added an assert that would have caught any of the problems I found
        - Handle clearing the inline cache properly in all cases

        * bindings/js/JSDOMBinding.cpp:
        (WebCore::cacheDOMObjectWrapper): Adjust for name changes.
        (WebCore::forgetDOMNode): Clear wrapper pointer.
        (WebCore::cacheDOMNodeWrapper): Cache inline too if caching for normal world.
        * bindings/js/JSDOMBinding.h:
        (WebCore::Document::getWrapperCache): Inlined.
        (WebCore::domObjectWrapperMapFor): Renamed to start with lowercase. Moved to header to inline.
        * bindings/js/JSDOMWrapper.h: Added.
        (WebCore::DOMObject::DOMObject): Factored this out of JSDOMBinding.h to avoid include
        cycle. I think the class should be renamed, I picked a forward-looking header name because
        we already have a DOMObject.h
        * bindings/js/JSNodeCustom.cpp:
        (WebCore::createWrapperInline): Renamed version of original createWrapper.
        (WebCore::createWrapper): Call createWrapperInline. Out-of-line version.
        (WebCore::toJSNewlyCreated): Call createWrapperInline instead of createWrapper.
        * bindings/js/JSNodeCustom.h: Added.
        (WebCore::getCachedDOMNodeWrapper): Moved from JSDOMBinding.cpp and moved here,
        so it could inline everywhere without creating an include cycle. Consider inline
        cache.
        (WebCore::toJS): Moved to header to inline.
        * bindings/js/ScriptWrappable.h:
        (WebCore::ScriptWrappable::ScriptWrappable): Implement this in the obvious
        way for JavaScriptCore. (Using a WeakGCPtr).
        (WebCore::ScriptWrappable::wrapper):
        (WebCore::ScriptWrappable::setWrapper):
        (WebCore::ScriptWrappable::clearWrapper):
        * bindings/scripts/CodeGeneratorJS.pm: Include CustomHeader heaaders
        in the header, not just the impl file, so they can add inlining.
        * dom/Node.idl: Add CustomHeader directive.

        Add new files to build.

        * GNUmakefile.am:
        * WebCore.gypi:
        * WebCore.pro:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:

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

14 files changed:
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSDOMBinding.cpp
WebCore/bindings/js/JSDOMBinding.h
WebCore/bindings/js/JSDOMWrapper.h [new file with mode: 0644]
WebCore/bindings/js/JSNodeCustom.cpp
WebCore/bindings/js/JSNodeCustom.h [new file with mode: 0644]
WebCore/bindings/js/ScriptWrappable.h
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/dom/Node.idl

index 6ab318fc2aed2f2bcdbc968f43dc3214459f4913..e8b257adfc3e6ade6ba1d2a6b1ed48393392e097 100644 (file)
@@ -1,3 +1,61 @@
+2010-02-24  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Cache JavaScript wrappers inline in DOM nodes
+        https://bugs.webkit.org/show_bug.cgi?id=35226
+
+        <rdar://problem/7664202>
+        
+        7.4% speedup on Dromaeo DOM Core tests.
+        2.3% speedup on Hixie DOM Core tests.
+
+        This fixes the following things from the last attempt:
+        - Now builds in both debug and release and passes all tests
+        - Properly use a WeakGCPtr, not just a raw pointer, in ScriptWrappable
+        - Properly look in the appropriate per-document or per-world map
+        - Added an assert that would have caught any of the problems I found
+        - Handle clearing the inline cache properly in all cases
+        
+        * bindings/js/JSDOMBinding.cpp:
+        (WebCore::cacheDOMObjectWrapper): Adjust for name changes.
+        (WebCore::forgetDOMNode): Clear wrapper pointer.
+        (WebCore::cacheDOMNodeWrapper): Cache inline too if caching for normal world.
+        * bindings/js/JSDOMBinding.h:
+        (WebCore::Document::getWrapperCache): Inlined.
+        (WebCore::domObjectWrapperMapFor): Renamed to start with lowercase. Moved to header to inline.
+        * bindings/js/JSDOMWrapper.h: Added.
+        (WebCore::DOMObject::DOMObject): Factored this out of JSDOMBinding.h to avoid include
+        cycle. I think the class should be renamed, I picked a forward-looking header name because
+        we already have a DOMObject.h
+        * bindings/js/JSNodeCustom.cpp:
+        (WebCore::createWrapperInline): Renamed version of original createWrapper.
+        (WebCore::createWrapper): Call createWrapperInline. Out-of-line version.
+        (WebCore::toJSNewlyCreated): Call createWrapperInline instead of createWrapper.
+        * bindings/js/JSNodeCustom.h: Added.
+        (WebCore::getCachedDOMNodeWrapper): Moved from JSDOMBinding.cpp and moved here,
+        so it could inline everywhere without creating an include cycle. Consider inline
+        cache.
+        (WebCore::toJS): Moved to header to inline.
+        * bindings/js/ScriptWrappable.h:
+        (WebCore::ScriptWrappable::ScriptWrappable): Implement this in the obvious
+        way for JavaScriptCore. (Using a WeakGCPtr).
+        (WebCore::ScriptWrappable::wrapper):
+        (WebCore::ScriptWrappable::setWrapper):
+        (WebCore::ScriptWrappable::clearWrapper):
+        * bindings/scripts/CodeGeneratorJS.pm: Include CustomHeader heaaders
+        in the header, not just the impl file, so they can add inlining.
+        * dom/Node.idl: Add CustomHeader directive.
+        
+        Add new files to build.
+
+        * GNUmakefile.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+
+
 2010-02-24  Jochen Eisinger  <jochen@chromium.org>
 
         Reviewed by Jeremy Orlow.
index c4bbc6a9c2de4a2f12fcfb57f599bbf22cab00ab..92f8103afe6813071789e5a26b1730d7a3f42b89 100644 (file)
@@ -380,6 +380,7 @@ webcore_sources += \
        WebCore/bindings/js/JSDOMWindowCustom.h \
        WebCore/bindings/js/JSDOMWindowShell.cpp \
        WebCore/bindings/js/JSDOMWindowShell.h \
+       WebCore/bindings/js/JSDOMWrapper.h \
        WebCore/bindings/js/JSDocumentCustom.cpp \
        WebCore/bindings/js/JSDocumentFragmentCustom.cpp \
        WebCore/bindings/js/JSElementCustom.cpp \
@@ -437,6 +438,7 @@ webcore_sources += \
        WebCore/bindings/js/JSNamedNodeMapCustom.cpp \
        WebCore/bindings/js/JSNavigatorCustom.cpp \
        WebCore/bindings/js/JSNodeCustom.cpp \
+       WebCore/bindings/js/JSNodeCustom.h \
        WebCore/bindings/js/JSNodeFilterCondition.cpp \
        WebCore/bindings/js/JSNodeFilterCondition.h \
        WebCore/bindings/js/JSNodeFilterCustom.cpp \
index 4c423c50dfc72f8f49a94215a4c44b5f6572caab..b3bd08a5a543b37acf56e47e2f2f51c76a92b5d4 100644 (file)
             'bindings/js/JSDOMWindowCustom.h',
             'bindings/js/JSDOMWindowShell.cpp',
             'bindings/js/JSDOMWindowShell.h',
+            'bindings/js/JSDOMWrapper.h',
             'bindings/js/JSElementCustom.cpp',
             'bindings/js/JSEventCustom.cpp',
             'bindings/js/JSEventListener.cpp',
             'bindings/js/JSNamedNodesCollection.h',
             'bindings/js/JSNavigatorCustom.cpp',
             'bindings/js/JSNodeCustom.cpp',
+            'bindings/js/JSNodeCustom.h',
             'bindings/js/JSNodeFilterCondition.cpp',
             'bindings/js/JSNodeFilterCondition.h',
             'bindings/js/JSNodeFilterCustom.cpp',
index 9caaba9ed3e630ff0223825ced3a16de996d52b7..a10683d791d5b9330ff44f3fcf20a30103ad73e0 100644 (file)
@@ -1018,6 +1018,7 @@ HEADERS += \
     bindings/js/JSDOMWindowBase.h \
     bindings/js/JSDOMWindowCustom.h \
     bindings/js/JSDOMWindowShell.h \
+    bindings/js/JSDOMWrapper.h \
     bindings/js/JSEventListener.h \
     bindings/js/JSEventSourceConstructor.h \
     bindings/js/JSEventTarget.h \
@@ -1031,6 +1032,7 @@ HEADERS += \
     bindings/js/JSLazyEventListener.h \
     bindings/js/JSLocationCustom.h \
     bindings/js/JSMessageChannelConstructor.h \
+    bindings/js/JSNodeCustom.h \
     bindings/js/JSNodeFilterCondition.h \
     bindings/js/JSOptionConstructor.h \
     bindings/js/JSPluginElementFunctions.h \
index dd936d82030fdd313690f7b775d4477eadbcbef0..e537e3599e36c439bca010beeeb69441ef9822ae 100644 (file)
                                        RelativePath="..\bindings\js\JSDOMWindowCustom.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\bindings\js\JSDOMWrapper.h"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\bindings\js\JSDOMWindowShell.cpp"\r
                                        >\r
                                                />\r
                                        </FileConfiguration>\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\bindings\js\JSNodeCustom.h"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\bindings\js\JSNodeFilterCondition.cpp"\r
                                        >\r
index 588b2b54c103ae2ed1d95f9f1e68794e6c548b81..04d40293f3889bb156008537d71965989d6f7abb 100644 (file)
                65DF323B09D1DE65000BE325 /* JSCanvasPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65DF323509D1DE65000BE325 /* JSCanvasPattern.cpp */; };
                65DF323C09D1DE65000BE325 /* JSCanvasPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DF323609D1DE65000BE325 /* JSCanvasPattern.h */; };
                65DF326109D1E199000BE325 /* UserAgentStyleSheetsData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 656581AF09D14EE6000E61D7 /* UserAgentStyleSheetsData.cpp */; };
+               65E0E9441133C89F00B4CB10 /* JSDOMWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E0E9431133C89F00B4CB10 /* JSDOMWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
                65FEA86909833ADE00BED4AB /* Page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65FEA86809833ADE00BED4AB /* Page.cpp */; };
                6E21C6C01126338500A7BE02 /* GraphicsContext3D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */; };
                6E21C6C21126339900A7BE02 /* GraphicsContext3DCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E21C6C11126339900A7BE02 /* GraphicsContext3DCG.cpp */; };
                65DF323409D1DE65000BE325 /* JSCanvasGradient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSCanvasGradient.h; sourceTree = "<group>"; };
                65DF323509D1DE65000BE325 /* JSCanvasPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSCanvasPattern.cpp; sourceTree = "<group>"; };
                65DF323609D1DE65000BE325 /* JSCanvasPattern.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSCanvasPattern.h; sourceTree = "<group>"; };
+               65E0E9431133C89F00B4CB10 /* JSDOMWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMWrapper.h; sourceTree = "<group>"; };
                65F80697054D9F86008BF776 /* BlockExceptions.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BlockExceptions.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                65FEA86809833ADE00BED4AB /* Page.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Page.cpp; sourceTree = "<group>"; };
                6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3D.cpp; sourceTree = "<group>"; };
                BC1A3793097C6FB10019F3D8 /* js */ = {
                        isa = PBXGroup;
                        children = (
+                               65E0E9431133C89F00B4CB10 /* JSDOMWrapper.h */,
                                BCCE58A71061E82F008FB35A /* Callback Objects */,
                                BCCE58B41061E925008FB35A /* Constructors */,
                                BC4EDEF70C08F414007EDD49 /* Custom */,
                                9F2A322E1125A0A2003C3056 /* JavaScriptProfileNode.h in Headers */,
                                7AFD4A8B1131C2760035B883 /* ScriptBreakpoint.h in Headers */,
                                7AFD4FF4113277B60035B883 /* ScriptDebugListener.h in Headers */,
+                               65E0E9441133C89F00B4CB10 /* JSDOMWrapper.h in Headers */,
                                5962297A1133EFE200DC4CBB /* GeolocationPositionCache.h in Headers */,
                                0BC2C7781134A8FC000B2F61 /* CanvasSurface.h in Headers */,
                        );
index abba40525ef071ff61807bb73ca41934b6471499..24e176e4111317610684bdb642d6b1ebd1cd00e1 100644 (file)
@@ -80,17 +80,6 @@ using namespace HTMLNames;
 typedef Document::JSWrapperCache JSWrapperCache;
 typedef Document::JSWrapperCacheMap JSWrapperCacheMap;
 
-inline JSWrapperCache* Document::getWrapperCache(DOMWrapperWorld* world)
-{
-    if (world->isNormal()) {
-        if (JSWrapperCache* wrapperCache = m_normalWorldWrapperCache)
-            return wrapperCache;
-        ASSERT(!m_wrapperCacheMap.contains(world));
-    } else if (JSWrapperCache* wrapperCache = m_wrapperCacheMap.get(world))
-        return wrapperCache;
-    return createWrapperCache(world);
-}
-
 // For debugging, keep a set of wrappers currently cached, and check that
 // all are uncached before they are destroyed. This helps us catch bugs like:
 //     - wrappers being deleted without being removed from the cache
@@ -221,11 +210,6 @@ const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const
     return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
 }
 
-static inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSC::ExecState* exec)
-{
-    return currentWorld(exec)->m_wrappers;
-}
-
 bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle)
 {
     for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) {
@@ -246,13 +230,13 @@ bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle)
 
 DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle) 
 {
-    return DOMObjectWrapperMapFor(exec).get(objectHandle);
+    return domObjectWrapperMapFor(exec).get(objectHandle);
 }
 
 void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper) 
 {
     willCacheWrapper(wrapper);
-    DOMObjectWrapperMapFor(exec).set(objectHandle, wrapper);
+    domObjectWrapperMapFor(exec).set(objectHandle, wrapper);
 }
 
 bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node)
@@ -268,13 +252,6 @@ bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node)
     return false;
 }
 
-JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node)
-{
-    if (document)
-        return document->getWrapperCache(currentWorld(exec))->get(node);
-    return static_cast<JSNode*>(DOMObjectWrapperMapFor(exec).get(node));
-}
-
 void forgetDOMObject(DOMObject* wrapper, void* objectHandle)
 {
     JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData();
@@ -299,6 +276,8 @@ void forgetDOMObject(DOMObject* wrapper, void* objectHandle)
 
 void forgetDOMNode(JSNode* wrapper, Node* node, Document* document)
 {
+    node->clearWrapper(wrapper);
+
     if (!document) {
         forgetDOMObject(wrapper, node);
         return;
@@ -316,13 +295,15 @@ void forgetDOMNode(JSNode* wrapper, Node* node, Document* document)
 
 void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper)
 {
-    if (!document) {
-        willCacheWrapper(wrapper);
-        DOMObjectWrapperMapFor(exec).set(node, wrapper);
-        return;
-    }
     willCacheWrapper(wrapper);
-    document->getWrapperCache(currentWorld(exec))->set(node, wrapper);
+
+    if (!document)
+        domObjectWrapperMapFor(exec).set(node, wrapper);
+    else
+        document->getWrapperCache(currentWorld(exec))->set(node, wrapper);
+
+    if (currentWorld(exec)->isNormal())
+        node->setWrapper(wrapper);
 }
 
 void forgetAllDOMNodesForDocument(Document* document)
index 807bf822d638c3051d062728cea7aa1c4cf04de2..62d71d496372ea25fe25d44d1c186771dbb1aacc 100644 (file)
@@ -23,6 +23,7 @@
 #define JSDOMBinding_h
 
 #include "JSDOMGlobalObject.h"
+#include "JSDOMWrapper.h"
 #include "JSSVGContextCache.h"
 #include "Document.h"
 #include <runtime/Completion.h>
@@ -52,21 +53,6 @@ namespace WebCore {
     class SVGElement;
 #endif
 
-    // Base class for all objects in this binding except Window.
-    class DOMObject : public JSC::JSObject {
-    protected:
-        explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure) 
-            : JSObject(structure)
-        {
-        }
-
-        virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool);
-
-#ifndef NDEBUG
-        virtual ~DOMObject();
-#endif
-    };
-
     // FIXME: This class should collapse into DOMObject once all DOMObjects are
     // updated to store a globalObject pointer.
     class DOMObjectWithGlobalPointer : public DOMObject {
@@ -446,6 +432,24 @@ namespace WebCore {
         return jsStringSlowCase(exec, stringCache, stringImpl);
     }
 
+    inline DOMObjectWrapperMap& domObjectWrapperMapFor(JSC::ExecState* exec)
+    {
+        return currentWorld(exec)->m_wrappers;
+    }
+
+
+
+    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 // JSDOMBinding_h
diff --git a/WebCore/bindings/js/JSDOMWrapper.h b/WebCore/bindings/js/JSDOMWrapper.h
new file mode 100644 (file)
index 0000000..dfb6d8c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ *  Copyright (C) 2009 Google, Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef JSDOMWrapper_h
+#define JSDOMWrapper_h
+
+#include <JavaScriptCore/JSObject.h>
+
+namespace WebCore {
+
+// Base class for all objects in this binding except Window.
+class DOMObject : public JSC::JSObject {
+protected:
+    explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure) 
+        : JSObject(structure)
+    {
+    }
+
+    virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool);
+
+#ifndef NDEBUG
+    virtual ~DOMObject();
+#endif
+};
+
+} // namespace WebCore
+
+#endif // JSDOMWrapper_h
index 46a30a4d2d7928090bb2b414d5bda55a44b1351a..134c5813a2b39ef11f4879466acb6df38f17f189 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -172,7 +172,7 @@ void JSNode::markChildren(MarkStack& markStack)
         markDOMNodeWrapper(markStack, m_impl->document(), nodeToMark);
 }
 
-static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
 {
     ASSERT(node);
     ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node));
@@ -228,25 +228,18 @@ static ALWAYS_INLINE JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* g
 
     return wrapper;    
 }
-    
-JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+
+JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
 {
-    if (!node)
-        return jsNull();
-    
-    return createWrapper(exec, globalObject, node);
+    return createWrapperInline(exec, globalObject, node);
 }
     
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
 {
     if (!node)
         return jsNull();
-
-    JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node);
-    if (wrapper)
-        return wrapper;
-
-    return createWrapper(exec, globalObject, node);
+    
+    return createWrapperInline(exec, globalObject, node);
 }
 
 } // namespace WebCore
diff --git a/WebCore/bindings/js/JSNodeCustom.h b/WebCore/bindings/js/JSNodeCustom.h
new file mode 100644 (file)
index 0000000..9d06ae6
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef JSNodeCustom_h
+#define JSNodeCustom_h
+
+#include "JSDOMBinding.h"
+#include <wtf/AlwaysInline.h>
+
+namespace WebCore {
+
+inline JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node)
+{
+    if (currentWorld(exec)->isNormal()) {
+        ASSERT(node->wrapper() == (document ? document->getWrapperCache(currentWorld(exec))->get(node) : domObjectWrapperMapFor(exec).get(node)));
+        return static_cast<JSNode*>(node->wrapper());
+    }
+
+    if (document)
+        return document->getWrapperCache(currentWorld(exec))->get(node);
+    return static_cast<JSNode*>(domObjectWrapperMapFor(exec).get(node));
+}
+
+JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Node*);
+
+inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+{
+    if (!node)
+        return JSC::jsNull();
+
+    JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node);
+    if (wrapper)
+        return wrapper;
+
+    return createWrapper(exec, globalObject, node);
+}
+
+}
+
+#endif // JSDOMNodeCustom_h
index d70cab75918b812c5e2c357b38e2cb34ba12fa07..eff6759bef43521d2b8c03e6ba977413a5f6f711 100644 (file)
 #ifndef ScriptWrappable_h
 #define ScriptWrappable_h
 
+#include "JSDOMWrapper.h"
+#include <JavaScriptCore/WeakGCPtr.h>
+
 namespace WebCore {
 
 class ScriptWrappable {
 public:
-    ScriptWrappable() { }
+    ScriptWrappable() : m_wrapper(0) { }
+    
+    DOMObject* wrapper() const
+    {
+        return m_wrapper.get();
+    }
+    
+    void setWrapper(DOMObject* wrapper)
+    {
+        ASSERT(wrapper);
+        m_wrapper = wrapper;
+    }
+    
+    void clearWrapper(DOMObject* wrapper) 
+    { 
+        m_wrapper.clear(wrapper); 
+    }
+    
+private:
+    JSC::WeakGCPtr<DOMObject> m_wrapper;
 };
 
 } // namespace WebCore
index 94fc2b850978498edcc2f7bfe961c78d417498ba..ece6df25d51eb8a1287b39f7319fb0d46e3491ca 100644 (file)
@@ -32,6 +32,7 @@ my $writeDependencies = 0;
 my @headerContentHeader = ();
 my @headerContent = ();
 my %headerIncludes = ();
+my %headerTrailingIncludes = ();
 
 my @implContentHeader = ();
 my @implContent = ();
@@ -551,7 +552,9 @@ sub GenerateHeader
     # Prototype
     push(@headerContent, "    static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});
 
-    $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"};
+    $headerTrailingIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"};
+
+    $implIncludes{"${className}Custom.h"} = 1 if !$dataNode->extendedAttributes->{"CustomHeader"} && ($dataNode->extendedAttributes->{"CustomPutFunction"} || $dataNode->extendedAttributes->{"DelegatingPutFunction"});
 
     my $hasGetter = $numAttributes > 0 
                  || !($dataNode->extendedAttributes->{"OmitConstructor"}
@@ -2246,12 +2249,23 @@ sub WriteData
         }
 
         print $HEADER @headerContent;
+
+        @includes = ();
+        foreach my $include (keys %headerTrailingIncludes) {
+            $include = "\"$include\"" unless $include =~ /^["<]/; # "
+            push @includes, $include;
+        }
+        foreach my $include (sort @includes) {
+            print $HEADER "#include $include\n";
+        }
+
         close($HEADER);
         undef($HEADER);
 
         @headerContentHeader = ();
         @headerContent = ();
         %headerIncludes = ();
+        %headerTrailingIncludes = ();
     }
 
     if (defined($DEPS)) {
index ca7874a57f8a97cf646161e3371e8674cdb89478..048931692b3be9ae30899900ebea4dd77f4fe998 100644 (file)
@@ -21,6 +21,7 @@
 module core {
 
     interface [
+        CustomHeader,
         CustomMarkFunction,
         CustomPushEventHandlerScope,
         CustomToJS,