Title: [90949] trunk/Source/WebCore
Revision
90949
Author
[email protected]
Date
2011-07-13 14:44:29 -0700 (Wed, 13 Jul 2011)

Log Message

2011-07-13  Vitaly Repeshko  <[email protected]>

        [V8] Avoid memory leaks with hidden references.
        https://bugs.webkit.org/show_bug.cgi?id=64467

        Reviewed by Adam Barth.

        We used to have growing arrays of hidden references associated
        with objects. The entries in this array had no keys and were never
        removed. This patch changes the interface to require a reference
        name. This way it's harder to leak an unbounded number of
        objects. Also it makes our wrapper objects one machine word
        smaller.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (90948 => 90949)


--- trunk/Source/WebCore/ChangeLog	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/ChangeLog	2011-07-13 21:44:29 UTC (rev 90949)
@@ -1,3 +1,55 @@
+2011-07-13  Vitaly Repeshko  <[email protected]>
+
+        [V8] Avoid memory leaks with hidden references.
+        https://bugs.webkit.org/show_bug.cgi?id=64467
+
+        Reviewed by Adam Barth.
+
+        We used to have growing arrays of hidden references associated
+        with objects. The entries in this array had no keys and were never
+        removed. This patch changes the interface to require a reference
+        name. This way it's harder to leak an unbounded number of
+        objects. Also it makes our wrapper objects one machine word
+        smaller.
+
+        * bindings/scripts/CodeGeneratorV8.pm:
+        (GenerateNormalAttrGetter): Started using new interface.
+
+        Interface changes:
+        * bindings/v8/V8DOMWrapper.cpp:
+        (WebCore::V8DOMWrapper::setNamedHiddenReference):
+        (WebCore::V8DOMWrapper::setNamedHiddenWindowReference):
+        * bindings/v8/V8DOMWrapper.h:
+
+        Added a helper to compute hidden reference names as V8 strings:
+        * bindings/v8/V8HiddenPropertyName.cpp:
+        (WebCore::V8HiddenPropertyName::hiddenReferenceName):
+        * bindings/v8/V8HiddenPropertyName.h:
+
+        * bindings/v8/WrapperTypeInfo.h: Removed the hidden reference
+        array internal field.
+
+        Update usages of hidden references:
+        * bindings/v8/custom/V8CSSStyleSheetCustom.cpp:
+        (WebCore::toV8):
+        * bindings/v8/custom/V8DOMStringMapCustom.cpp:
+        (WebCore::toV8):
+        * bindings/v8/custom/V8DOMTokenListCustom.cpp:
+        (WebCore::toV8):
+        * bindings/v8/custom/V8LocationCustom.cpp:
+        (WebCore::toV8):
+        * bindings/v8/custom/V8MessageChannelConstructor.cpp:
+        (WebCore::V8MessageChannel::constructorCallback):
+        * bindings/v8/custom/V8NamedNodeMapCustom.cpp:
+        (WebCore::toV8):
+        * bindings/v8/custom/V8StyleSheetCustom.cpp:
+        (WebCore::toV8):
+        * bindings/v8/custom/V8WebGLRenderingContextCustom.cpp:
+        (WebCore::toV8Object):
+
+        * bindings/scripts/test/V8/V8TestObj.cpp:
+        (WebCore::TestObjInternal::readOnlyTestObjAttrAttrGetter): Updated.
+
 2011-07-13  Joseph Pecoraro  <[email protected]>
 
         Improve names of some ApplicationCacheStorage accessor methods

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm (90948 => 90949)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm	2011-07-13 21:44:29 UTC (rev 90949)
@@ -856,9 +856,9 @@
         push(@implContentDecls, "        wrapper = toV8(result.get());\n");
         push(@implContentDecls, "        if (!wrapper.IsEmpty())\n");
         if ($dataNode->name eq "DOMWindow") {
-            push(@implContentDecls, "            V8DOMWrapper::setHiddenWindowReference(imp->frame(), wrapper);\n");
+            push(@implContentDecls, "            V8DOMWrapper::setNamedHiddenWindowReference(imp->frame(), \"${attrName}\", wrapper);\n");
         } else {
-            push(@implContentDecls, "            V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);\n");
+            push(@implContentDecls, "            V8DOMWrapper::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n");
         }
         push(@implContentDecls, "    }\n");
         push(@implContentDecls, "    return wrapper;\n");

Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -76,7 +76,7 @@
     if (wrapper.IsEmpty()) {
         wrapper = toV8(result.get());
         if (!wrapper.IsEmpty())
-            V8DOMWrapper::setHiddenReference(info.Holder(), wrapper);
+            V8DOMWrapper::setNamedHiddenReference(info.Holder(), "readOnlyTestObjAttr", wrapper);
     }
     return wrapper;
 }

Modified: trunk/Source/WebCore/bindings/v8/V8DOMWrapper.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/V8DOMWrapper.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/V8DOMWrapper.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -31,6 +31,7 @@
 #include "config.h"
 #include "V8DOMWrapper.h"
 
+#include "ArrayBufferView.h"
 #include "CSSMutableStyleDeclaration.h"
 #include "DOMDataStore.h"
 #include "DocumentLoader.h"
@@ -39,10 +40,10 @@
 #include "V8AbstractEventListener.h"
 #include "V8Binding.h"
 #include "V8Collection.h"
-#include "V8DedicatedWorkerContext.h"
 #include "V8DOMApplicationCache.h"
 #include "V8DOMMap.h"
 #include "V8DOMWindow.h"
+#include "V8DedicatedWorkerContext.h"
 #include "V8EventListener.h"
 #include "V8EventListenerList.h"
 #include "V8EventSource.h"
@@ -51,6 +52,7 @@
 #include "V8FileWriter.h"
 #include "V8HTMLCollection.h"
 #include "V8HTMLDocument.h"
+#include "V8HiddenPropertyName.h"
 #include "V8IDBDatabase.h"
 #include "V8IDBRequest.h"
 #include "V8IDBTransaction.h"
@@ -75,7 +77,6 @@
 #include "V8WorkerContext.h"
 #include "V8WorkerContextEventListener.h"
 #include "V8XMLHttpRequest.h"
-#include "ArrayBufferView.h"
 #include "WebGLContextAttributes.h"
 #include "WebGLUniformLocation.h"
 #include "WorkerContextExecutionProxy.h"
@@ -189,18 +190,13 @@
 }
 #endif
 
-void V8DOMWrapper::setHiddenReference(v8::Handle<v8::Object> parent, v8::Handle<v8::Value> child)
+
+void V8DOMWrapper::setNamedHiddenReference(v8::Handle<v8::Object> parent, const char* name, v8::Handle<v8::Value> child)
 {
-    v8::Local<v8::Value> hiddenReferenceObject = parent->GetInternalField(v8DOMHiddenReferenceArrayIndex);
-    if (hiddenReferenceObject->IsNull() || hiddenReferenceObject->IsUndefined()) {
-        hiddenReferenceObject = v8::Array::New();
-        parent->SetInternalField(v8DOMHiddenReferenceArrayIndex, hiddenReferenceObject);
-    }
-    v8::Local<v8::Array> hiddenReferenceArray = v8::Local<v8::Array>::Cast(hiddenReferenceObject);
-    hiddenReferenceArray->Set(v8::Integer::New(hiddenReferenceArray->Length()), child);
+    parent->SetHiddenValue(V8HiddenPropertyName::hiddenReferenceName(name), child);
 }
 
-void V8DOMWrapper::setHiddenWindowReference(Frame* frame, v8::Handle<v8::Value> jsObject)
+void V8DOMWrapper::setNamedHiddenWindowReference(Frame* frame, const char* name, v8::Handle<v8::Value> jsObject)
 {
     // Get DOMWindow
     if (!frame)
@@ -214,7 +210,7 @@
     global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global);
     ASSERT(!global.IsEmpty());
 
-    setHiddenReference(global, jsObject);
+    setNamedHiddenReference(global, name, jsObject);
 }
 
 WrapperTypeInfo* V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object)

Modified: trunk/Source/WebCore/bindings/v8/V8DOMWrapper.h (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/V8DOMWrapper.h	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/V8DOMWrapper.h	2011-07-13 21:44:29 UTC (rev 90949)
@@ -114,11 +114,15 @@
         // Check whether a V8 value is a wrapper of type |classType|.
         static bool isWrapperOfType(v8::Handle<v8::Value>, WrapperTypeInfo*);
 
-        static void setHiddenReference(v8::Handle<v8::Object> parent, v8::Handle<v8::Value> child);
+        // Proper object lifetime support.
+        //
+        // Helper functions to make sure the child object stays alive
+        // while the parent is alive. Using the name more than once
+        // overwrites previous references making it possible to free
+        // old children.
+        static void setNamedHiddenReference(v8::Handle<v8::Object> parent, const char* name, v8::Handle<v8::Value> child);
+        static void setNamedHiddenWindowReference(Frame*, const char*, v8::Handle<v8::Value>);
 
-        // Set hidden references in a DOMWindow object of a frame.
-        static void setHiddenWindowReference(Frame*, v8::Handle<v8::Value>);
-
         static v8::Local<v8::Object> instantiateV8Object(V8Proxy* proxy, WrapperTypeInfo*, void* impl);
 
         static v8::Handle<v8::Object> getWrapper(Node* node)

Modified: trunk/Source/WebCore/bindings/v8/V8HiddenPropertyName.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/V8HiddenPropertyName.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/V8HiddenPropertyName.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -31,6 +31,9 @@
 #include "config.h"
 #include "V8HiddenPropertyName.h"
 
+#include <string.h>
+#include <wtf/Vector.h>
+
 namespace WebCore {
 
 #define V8_AS_STRING(x) V8_AS_STRING_IMPL(x)
@@ -39,12 +42,22 @@
 #define V8_DEFINE_PROPERTY(name) \
 v8::Handle<v8::String> V8HiddenPropertyName::name() \
 { \
-    static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::" V8_AS_STRING(name)); \
+    static v8::Persistent<v8::String>* string = createString("WebCore::HiddenProperty::" V8_AS_STRING(name)); \
     return *string; \
 }
 
 V8_HIDDEN_PROPERTIES(V8_DEFINE_PROPERTY);
 
+static const char hiddenReferenceNamePrefix[] = "WebCore::HiddenReference::";
+
+v8::Handle<v8::String> V8HiddenPropertyName::hiddenReferenceName(const char* name)
+{
+    Vector<char, 64> prefixedName;
+    prefixedName.append(hiddenReferenceNamePrefix, sizeof(hiddenReferenceNamePrefix) - 1);
+    prefixedName.append(name, strlen(name));
+    return v8::String::NewSymbol(prefixedName.data(), static_cast<int>(prefixedName.size()));
+}
+
 v8::Persistent<v8::String>* V8HiddenPropertyName::createString(const char* key)
 {
     v8::HandleScope scope;

Modified: trunk/Source/WebCore/bindings/v8/V8HiddenPropertyName.h (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/V8HiddenPropertyName.h	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/V8HiddenPropertyName.h	2011-07-13 21:44:29 UTC (rev 90949)
@@ -52,6 +52,8 @@
         V8_HIDDEN_PROPERTIES(V8_DECLARE_PROPERTY);
 #undef V8_DECLARE_PROPERTY
 
+        static v8::Handle<v8::String> hiddenReferenceName(const char* name);
+
     private:
         static v8::Persistent<v8::String>* createString(const char* key);
     };

Modified: trunk/Source/WebCore/bindings/v8/WrapperTypeInfo.h (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/WrapperTypeInfo.h	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/WrapperTypeInfo.h	2011-07-13 21:44:29 UTC (rev 90949)
@@ -39,8 +39,7 @@
     
     static const int v8DOMWrapperTypeIndex = 0;
     static const int v8DOMWrapperObjectIndex = 1;
-    static const int v8DOMHiddenReferenceArrayIndex = 2;
-    static const int v8DefaultWrapperInternalFieldCount = 3;
+    static const int v8DefaultWrapperInternalFieldCount = 2;
 
     static const uint16_t v8DOMSubtreeClassId = 1;
 

Modified: trunk/Source/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -44,7 +44,7 @@
     // Add a hidden reference from stylesheet object to its owner node.
     Node* ownerNode = impl->ownerNode();
     if (ownerNode && !wrapper.IsEmpty())
-        V8DOMWrapper::setHiddenReference(wrapper, toV8(ownerNode));
+        V8DOMWrapper::setNamedHiddenReference(wrapper, "ownerNode", toV8(ownerNode));
     return wrapper;
 }
 

Modified: trunk/Source/WebCore/bindings/v8/custom/V8DOMStringMapCustom.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8DOMStringMapCustom.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8DOMStringMapCustom.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -105,7 +105,7 @@
     if (!wrapper.IsEmpty() && element) {
         v8::Handle<v8::Value> elementValue = toV8(element);
         if (!elementValue.IsEmpty() && elementValue->IsObject())
-            V8DOMWrapper::setHiddenReference(elementValue.As<v8::Object>(), wrapper);
+            V8DOMWrapper::setNamedHiddenReference(elementValue.As<v8::Object>(), "domStringMap", wrapper);
     }
     return wrapper;
 }

Modified: trunk/Source/WebCore/bindings/v8/custom/V8DOMTokenListCustom.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8DOMTokenListCustom.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8DOMTokenListCustom.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -48,7 +48,7 @@
     if (!wrapper.IsEmpty() && element) {
         v8::Handle<v8::Value> elementValue = toV8(element);
         if (!elementValue.IsEmpty() && elementValue->IsObject())
-            V8DOMWrapper::setHiddenReference(elementValue.As<v8::Object>(), wrapper);
+            V8DOMWrapper::setNamedHiddenReference(elementValue.As<v8::Object>(), "domTokenList", wrapper);
     }
     return wrapper;
 }

Modified: trunk/Source/WebCore/bindings/v8/custom/V8LocationCustom.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8LocationCustom.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8LocationCustom.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -280,7 +280,7 @@
     if (wrapper.IsEmpty()) {
         wrapper = V8Location::wrap(impl);
         if (!wrapper.IsEmpty())
-            V8DOMWrapper::setHiddenWindowReference(impl->frame(), wrapper);
+            V8DOMWrapper::setNamedHiddenWindowReference(impl->frame(), "location", wrapper);
     }
     return wrapper;
 }

Modified: trunk/Source/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -67,8 +67,8 @@
     // Create references from the MessageChannel wrapper to the two
     // MessagePort wrappers to make sure that the MessagePort wrappers
     // stay alive as long as the MessageChannel wrapper is around.
-    V8DOMWrapper::setHiddenReference(messageChannel, toV8(obj->port1()));
-    V8DOMWrapper::setHiddenReference(messageChannel, toV8(obj->port2()));
+    V8DOMWrapper::setNamedHiddenReference(messageChannel, "port1", toV8(obj->port1()));
+    V8DOMWrapper::setNamedHiddenReference(messageChannel, "port2", toV8(obj->port2()));
 
     // Setup the standard wrapper object internal fields.
     V8DOMWrapper::setDOMWrapper(messageChannel, &info, obj.get());

Modified: trunk/Source/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -83,7 +83,7 @@
     // Add a hidden reference from named node map to its owner node.
     Element* element = impl->element();
     if (!wrapper.IsEmpty() && element)
-        V8DOMWrapper::setHiddenReference(wrapper, toV8(element));
+        V8DOMWrapper::setNamedHiddenReference(wrapper, "ownerNode", toV8(element));
     return wrapper;
 }
 

Modified: trunk/Source/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -47,7 +47,7 @@
     // Add a hidden reference from stylesheet object to its owner node.
     Node* ownerNode = impl->ownerNode();
     if (ownerNode && !wrapper.IsEmpty())
-        V8DOMWrapper::setHiddenReference(wrapper, toV8(ownerNode));
+        V8DOMWrapper::setNamedHiddenReference(wrapper, "ownerNode", toV8(ownerNode));
     return wrapper;
 }
 

Modified: trunk/Source/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp (90948 => 90949)


--- trunk/Source/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp	2011-07-13 21:40:54 UTC (rev 90948)
+++ trunk/Source/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp	2011-07-13 21:44:29 UTC (rev 90949)
@@ -161,22 +161,27 @@
     if (!extension)
         return v8::Null();
     v8::Handle<v8::Value> extensionObject;
+    const char* referenceName;
     switch (extension->getName()) {
     case WebGLExtension::WebKitLoseContextName:
         extensionObject = toV8(static_cast<WebKitLoseContext*>(extension));
+        referenceName = "webKitLoseContextName";
         break;
     case WebGLExtension::OESStandardDerivativesName:
         extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension));
+        referenceName = "oesStandardDerivativesName";
         break;
     case WebGLExtension::OESTextureFloatName:
         extensionObject = toV8(static_cast<OESTextureFloat*>(extension));
+        referenceName = "oesTextureFloatName";
         break;
     case WebGLExtension::OESVertexArrayObjectName:
         extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension));
+        referenceName = "oesVertexArrayObjectName";
         break;
     }
     ASSERT(!extensionObject.IsEmpty());
-    V8DOMWrapper::setHiddenReference(contextObject, extensionObject);
+    V8DOMWrapper::setNamedHiddenReference(contextObject, referenceName, extensionObject);
     return extensionObject;
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to