Title: [135152] trunk
Revision
135152
Author
loi...@chromium.org
Date
2012-11-19 06:53:38 -0800 (Mon, 19 Nov 2012)

Log Message

webaudio: leak: AudioContext objects are leaking. They retain 36mb of shared data.
https://bugs.webkit.org/show_bug.cgi?id=102356

Reviewed by Adam Barth.

A clean-up code was moved from uninitialize to clear method.
AudioContext marks itself as hasPendingActivity in method constructCommon and unmarks itself in method clear.
m_isStopScheduled filters out second ActiveDOMObject::stop call.
markForDeletion appends AudioNode pointer to m_nodesToDelete array if there is no active audio thread.
adoptRef was added in createOfflineContext method.
A guard was added into deleteMarkedNodes.

Source/WebCore:

Test: inspector-protocol/nmi-webaudio-leak-test.html

* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::createOfflineContext):
(WebCore::AudioContext::AudioContext):
(WebCore::AudioContext::constructCommon):
(WebCore::AudioContext::~AudioContext):
(WebCore::AudioContext::clear):
(WebCore::AudioContext::uninitialize):
(WebCore::AudioContext::stopDispatch):
(WebCore::AudioContext::stop):
(WebCore::AudioContext::markForDeletion):
(WebCore::AudioContext::scheduleNodeDeletion):
(WebCore::AudioContext::deleteMarkedNodes):
* Modules/webaudio/AudioContext.h:
(AudioContext):
* bindings/v8/custom/V8AudioContextCustom.cpp:
(WebCore::V8AudioContext::constructorCallback):
* inspector/InspectorMemoryAgent.cpp:
(WebCore::InspectorMemoryAgent::getProcessMemoryDistribution):
* platform/PlatformMemoryInstrumentation.cpp:
(WebCore::PlatformMemoryInstrumentation::reportMemoryUsage):
(WebCore):
* platform/PlatformMemoryInstrumentation.h:
(PlatformMemoryInstrumentation):
(WebCore):

LayoutTests:

* inspector-protocol/nmi-webaudio-leak-test-expected.txt: Added.
* inspector-protocol/nmi-webaudio-leak-test.html: Added.
* platform/chromium-android/TestExpectations:
* platform/efl-wk2/TestExpectations:
* platform/efl/TestExpectations:
* platform/gtk/TestExpectations:
* platform/mac/TestExpectations:
* platform/qt/TestExpectations:
* platform/win/TestExpectations:
* platform/wincairo/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (135151 => 135152)


--- trunk/LayoutTests/ChangeLog	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/ChangeLog	2012-11-19 14:53:38 UTC (rev 135152)
@@ -1,3 +1,28 @@
+2012-11-19  Ilya Tikhonovsky  <loi...@chromium.org>
+
+        webaudio: leak: AudioContext objects are leaking. They retain 36mb of shared data.
+        https://bugs.webkit.org/show_bug.cgi?id=102356
+
+        Reviewed by Adam Barth.
+
+        A clean-up code was moved from uninitialize to clear method.
+        AudioContext marks itself as hasPendingActivity in method constructCommon and unmarks itself in method clear.
+        m_isStopScheduled filters out second ActiveDOMObject::stop call.
+        markForDeletion appends AudioNode pointer to m_nodesToDelete array if there is no active audio thread.
+        adoptRef was added in createOfflineContext method.
+        A guard was added into deleteMarkedNodes.
+
+        * inspector-protocol/nmi-webaudio-leak-test-expected.txt: Added.
+        * inspector-protocol/nmi-webaudio-leak-test.html: Added.
+        * platform/chromium-android/TestExpectations:
+        * platform/efl-wk2/TestExpectations:
+        * platform/efl/TestExpectations:
+        * platform/gtk/TestExpectations:
+        * platform/mac/TestExpectations:
+        * platform/qt/TestExpectations:
+        * platform/win/TestExpectations:
+        * platform/wincairo/TestExpectations:
+
 2012-11-19  Erik Arvidsson  <a...@chromium.org>
 
         Update DOMException name: QuotaExceededError

Added: trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test-expected.txt (0 => 135152)


--- trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test-expected.txt	2012-11-19 14:53:38 UTC (rev 135152)
@@ -0,0 +1,9 @@
+This test is checking that AudioContext is deleting after navigation. It is not possible to count AudioContext objects directly. But we could use Native Memory Snapshot which has information about Page.Audio.SharedData. All the shared data are retained by HRTFDatabaseLoader refcounted singleton and Native Memory Instrumentation is visiting it via public getter. 
+
+Action: Wait for Page.Audio data
+PASS: Memory size for Page.Audio more than 15000000
+Action: Navigate IFrame to resources/blank.html
+PASS: IFrame was navigated to resources/blank.html
+Action: Run GC and check Page.Audio data size
+PASS: No Page.Audio data found
+
Property changes on: trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test-expected.txt
___________________________________________________________________

Added: svn:eol-style

Added: trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test.html (0 => 135152)


--- trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test.html	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test.html	2012-11-19 14:53:38 UTC (rev 135152)
@@ -0,0 +1,105 @@
+<html>
+<head>
+<script src=""
+<script>
+
+function runTestOnlyOnce()
+{
+    if (window.testFirstRun)
+        return;
+    window.testFirstRun = 1;
+
+    runTest();
+}
+
+function navigateIFrame()
+{
+    var iframe = document.getElementById("iframe");
+    iframe.src = ""
+}
+
+function test()
+{
+    function sizeForType(entry, typeNames)
+    {
+        for (var index = 0; index < typeNames.length; ++index) {
+            var typeName = typeNames[index];
+            var found = 0;
+            for (var i = 0; i < entry.children.length; ++i) {
+                var childEntry = entry.children[i];
+                if (childEntry.name === typeName) {
+                    if (index === typeNames.length - 1)
+                        return childEntry.size;
+
+                    if (!childEntry.children)
+                        return -1;
+
+                    entry = childEntry;
+                    found = 1;
+                    break;
+                }
+            }
+            if (!found)
+                return -1;
+        }
+
+        return -1;
+    }
+
+    var pivotSize = 15000000;
+
+    function noAudioSharedData(messageObject)
+    {
+        var size = sizeForType(messageObject["result"]["distribution"], ["Page", "Audio"]);
+        if (size === -1)
+            InspectorTest.log("PASS: No Page.Audio data found");
+        else
+            InspectorTest.log("FAIL: " + size + " bytes of Page.Audio data was found");
+        InspectorTest.completeTest();
+    }
+
+    function iFrameNavigated(messageObject) {
+        InspectorTest.log("PASS: IFrame was navigated to resources/blank.html");
+        InspectorTest.sendCommand('Profiler.collectGarbage', {}, function() { } );
+        InspectorTest.log("Action: Run GC and check Page.Audio data size");
+        InspectorTest.sendCommand('Memory.getProcessMemoryDistribution', {}, noAudioSharedData);
+    }
+
+    function waitForSharedAudioData(messageObject) {
+        var size = sizeForType(messageObject["result"]["distribution"], ["Page", "Audio"]);
+        if (size === -1) {
+            InspectorTest.log("FAIL: No Page.Audio data was found.");
+            InspectorTest.completeTest();
+            return;
+        }
+        if (size < pivotSize)
+            InspectorTest.sendCommand('Memory.getProcessMemoryDistribution', {}, waitForSharedAudioData);
+        else {
+            InspectorTest.log("PASS: Memory size for Page.Audio more than " + pivotSize);
+
+            InspectorTest.sendCommand('Page.enable', {}, function() { } );
+
+            InspectorTest.log("Action: Navigate IFrame to resources/blank.html");
+            InspectorTest.eventHandler["Page.frameNavigated"] = iFrameNavigated;
+            InspectorTest.sendCommand('Runtime.evaluate', {_expression_: 'navigateIFrame()'}, function() { } );
+        }
+    }
+
+    InspectorTest.log("");
+    InspectorTest.log("Action: Wait for Page.Audio data");
+    InspectorTest.sendCommand('Memory.getProcessMemoryDistribution', {}, waitForSharedAudioData);
+}
+</script>
+</head>
+<body _onload_="testRunner.waitUntilDone()">
+This test is checking that AudioContext is deleting after navigation.
+It is not possible to count AudioContext objects directly.
+But we could use Native Memory Snapshot which has information about Page.Audio.SharedData.
+All the shared data are retained by HRTFDatabaseLoader refcounted singleton
+and Native Memory Instrumentation is visiting it via public getter.
+
+<iframe id="iframe" _onLoad_="runTestOnlyOnce()" src="" >
+</iframe>
+
+</body>
+</html>
Property changes on: trunk/LayoutTests/inspector-protocol/nmi-webaudio-leak-test.html
___________________________________________________________________

Added: svn:mime-type

Added: svn:eol-style

Modified: trunk/LayoutTests/platform/chromium-android/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/chromium-android/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/chromium-android/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -57,7 +57,10 @@
 crbug.com/145338 platform/chromium/fast/forms/color
 crbug.com/145338 platform/chromium/media/video-capture-preview.html # Uses mediastream
 crbug.com/145338 webaudio
+crbug.com/145338 inspector-protocol/nmi-webaudio.html
+crbug.com/145338 inspector-protocol/nmi-webaudio-leak-test.html
 
+
 # This test is only for GTK which is not applicable to Android.
 platform/chromium-linux/fast/text/chromium-linux-fontconfig-renderstyle.html [ WontFix ]
 

Modified: trunk/LayoutTests/platform/efl/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/efl/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/efl/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -1142,7 +1142,10 @@
 
 # Requires WEB_AUDIO support.
 webkit.org/b/91738 webaudio [ Skip ]
+inspector-protocol/nmi-webaudio.html
+inspector-protocol/nmi-webaudio-leak-test.html
 
+
 # Requires MEDIA_STREAM support.
 webkit.org/b/87662 fast/mediastream [ Skip ]
 

Modified: trunk/LayoutTests/platform/efl-wk2/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/efl-wk2/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/efl-wk2/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -297,3 +297,4 @@
 webkit.org/b/102202 inspector/timeline/timeline-timer-fired-from-eval-call-site.html [ Failure ]
 
 webkit.org/b/102216 inspector-protocol/nmi-webaudio.html [ Failure ]
+webkit.org/b/102216 inspector-protocol/nmi-webaudio-leak-test.html [ Failure ]

Modified: trunk/LayoutTests/platform/gtk/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/gtk/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/gtk/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -290,6 +290,9 @@
 
 # For now, Web Audio API is disabled
 webkit.org/b/67187 webaudio [ Skip ]
+webkit.org/b/67187 inspector-protocol/nmi-webaudio.html
+webkit.org/b/67187 inspector-protocol/nmi-webaudio-leak-test.html
+
 # These tests include proprietary codecs.
 webkit.org/b/67187 webaudio/codec-tests
 

Modified: trunk/LayoutTests/platform/mac/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/mac/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -450,6 +450,8 @@
 # For now, Web Audio tests are disabled
 # https://bugs.webkit.org/show_bug.cgi?id=86914
 webaudio/
+inspector-protocol/nmi-webaudio.html
+inspector-protocol/nmi-webaudio-leak-test.html
 
 # Microdata DOM API is not yet enabled.
 fast/dom/MicroData

Modified: trunk/LayoutTests/platform/qt/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/qt/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/qt/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -403,6 +403,7 @@
 # For now, Web Audio API is disabled
 webaudio/
 webkit.org/b/101729 inspector-protocol/nmi-webaudio.html
+webkit.org/b/101729 inspector-protocol/nmi-webaudio-leak-test.html
 
 # [Qt] Enable WebGL by default for QtWebKit
 # https://bugs.webkit.org/show_bug.cgi?id=65998

Modified: trunk/LayoutTests/platform/win/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/win/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/win/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -1542,6 +1542,8 @@
 
 # For now, Web Audio API is disabled
 webaudio/
+inspector-protocol/nmi-webaudio.html
+inspector-protocol/nmi-webaudio-leak-test.html
 
 # The win port has no support for <track>
 # https://bugs.webkit.org/show_bug.cgi?id=43668

Modified: trunk/LayoutTests/platform/wincairo/TestExpectations (135151 => 135152)


--- trunk/LayoutTests/platform/wincairo/TestExpectations	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/LayoutTests/platform/wincairo/TestExpectations	2012-11-19 14:53:38 UTC (rev 135152)
@@ -2075,7 +2075,10 @@
 
 # For now, Web Audio API is disabled
 webaudio/
+inspector-protocol/nmi-webaudio.html
+inspector-protocol/nmi-webaudio-leak-test.html
 
+
 # The win port has no support for <track>
 # https://bugs.webkit.org/show_bug.cgi?id=43668
 media/track

Modified: trunk/Source/WebCore/ChangeLog (135151 => 135152)


--- trunk/Source/WebCore/ChangeLog	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/Source/WebCore/ChangeLog	2012-11-19 14:53:38 UTC (rev 135152)
@@ -1,3 +1,44 @@
+2012-11-19  Ilya Tikhonovsky  <loi...@chromium.org>
+
+        webaudio: leak: AudioContext objects are leaking. They retain 36mb of shared data.
+        https://bugs.webkit.org/show_bug.cgi?id=102356
+
+        Reviewed by Adam Barth.
+
+        A clean-up code was moved from uninitialize to clear method.
+        AudioContext marks itself as hasPendingActivity in method constructCommon and unmarks itself in method clear.
+        m_isStopScheduled filters out second ActiveDOMObject::stop call.
+        markForDeletion appends AudioNode pointer to m_nodesToDelete array if there is no active audio thread.
+        adoptRef was added in createOfflineContext method.
+        A guard was added into deleteMarkedNodes.
+
+        Test: inspector-protocol/nmi-webaudio-leak-test.html
+
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::createOfflineContext):
+        (WebCore::AudioContext::AudioContext):
+        (WebCore::AudioContext::constructCommon):
+        (WebCore::AudioContext::~AudioContext):
+        (WebCore::AudioContext::clear):
+        (WebCore::AudioContext::uninitialize):
+        (WebCore::AudioContext::stopDispatch):
+        (WebCore::AudioContext::stop):
+        (WebCore::AudioContext::markForDeletion):
+        (WebCore::AudioContext::scheduleNodeDeletion):
+        (WebCore::AudioContext::deleteMarkedNodes):
+        * Modules/webaudio/AudioContext.h:
+        (AudioContext):
+        * bindings/v8/custom/V8AudioContextCustom.cpp:
+        (WebCore::V8AudioContext::constructorCallback):
+        * inspector/InspectorMemoryAgent.cpp:
+        (WebCore::InspectorMemoryAgent::getProcessMemoryDistribution):
+        * platform/PlatformMemoryInstrumentation.cpp:
+        (WebCore::PlatformMemoryInstrumentation::reportMemoryUsage):
+        (WebCore):
+        * platform/PlatformMemoryInstrumentation.h:
+        (PlatformMemoryInstrumentation):
+        (WebCore):
+
 2012-11-19  Erik Arvidsson  <a...@chromium.org>
 
         Update DOMException name: QuotaExceededError

Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp (135151 => 135152)


--- trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp	2012-11-19 14:53:38 UTC (rev 135152)
@@ -135,7 +135,7 @@
         return 0;
     }
 
-    RefPtr<AudioContext> audioContext(new AudioContext(document, numberOfChannels, numberOfFrames, sampleRate));
+    RefPtr<AudioContext> audioContext(adoptRef(new AudioContext(document, numberOfChannels, numberOfFrames, sampleRate)));
     audioContext->suspendIfNeeded();
     return audioContext.release();
 }
@@ -143,6 +143,7 @@
 // Constructor for rendering to the audio hardware.
 AudioContext::AudioContext(Document* document)
     : ActiveDOMObject(document, this)
+    , m_isStopScheduled(false)
     , m_isInitialized(false)
     , m_isAudioThreadFinished(false)
     , m_document(document)
@@ -169,6 +170,7 @@
 // Constructor for offline (non-realtime) rendering.
 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
     : ActiveDOMObject(document, this)
+    , m_isStopScheduled(false)
     , m_isInitialized(false)
     , m_isAudioThreadFinished(false)
     , m_document(document)
@@ -192,6 +194,10 @@
 
 void AudioContext::constructCommon()
 {
+    // According to spec AudioContext must die only after page navigate.
+    // Lets mark it as ActiveDOMObject with pending activity and unmark it in clear method.
+    setPendingActivity(this);
+
 #if USE(GSTREAMER)
     initializeGStreamer();
 #endif
@@ -207,6 +213,8 @@
     fprintf(stderr, "%p: AudioContext::~AudioContext()\n", this);
 #endif
     // AudioNodes keep a reference to their context, so there should be no way to be in the destructor if there are still AudioNodes around.
+    ASSERT(!m_isInitialized);
+    ASSERT(m_isStopScheduled);
     ASSERT(!m_nodesToDelete.size());
     ASSERT(!m_referencedNodes.size());
     ASSERT(!m_finishedNodes.size());
@@ -238,35 +246,45 @@
     }
 }
 
+void AudioContext::clear()
+{
+    // We have to release our reference to the destination node before the context will ever be deleted since the destination node holds a reference to the context.
+    if (m_destinationNode)
+        m_destinationNode.clear();
+
+    // Audio thread is dead. Nobody will schedule node deletion action. Let's do it ourselves.
+    do {
+        deleteMarkedNodes();
+        m_nodesToDelete.append(m_nodesMarkedForDeletion);
+        m_nodesMarkedForDeletion.clear();
+    } while (m_nodesToDelete.size());
+
+    // It was set in constructCommon.
+    unsetPendingActivity(this);
+}
+
 void AudioContext::uninitialize()
 {
     ASSERT(isMainThread());
 
-    if (m_isInitialized) {
-        // Protect this object from being deleted before we finish uninitializing.
-        RefPtr<AudioContext> protect(this);
+    if (!m_isInitialized)
+        return;
 
-        // This stops the audio thread and all audio rendering.
-        m_destinationNode->uninitialize();
+    // This stops the audio thread and all audio rendering.
+    m_destinationNode->uninitialize();
 
-        // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
-        m_isAudioThreadFinished = true;
+    // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
+    m_isAudioThreadFinished = true;
 
-        // We have to release our reference to the destination node before the context will ever be deleted since the destination node holds a reference to the context.
-        m_destinationNode.clear();
+    if (!isOfflineContext()) {
+        ASSERT(s_hardwareContextCount);
+        --s_hardwareContextCount;
+    }
 
-        if (!isOfflineContext()) {
-            ASSERT(s_hardwareContextCount);
-            --s_hardwareContextCount;
-        }
-        
-        // Get rid of the sources which may still be playing.
-        derefUnfinishedSourceNodes();
+    // Get rid of the sources which may still be playing.
+    derefUnfinishedSourceNodes();
 
-        deleteMarkedNodes();
-
-        m_isInitialized = false;
-    }
+    m_isInitialized = false;
 }
 
 bool AudioContext::isInitialized() const
@@ -283,7 +301,7 @@
     return m_hrtfDatabaseLoader->isLoaded();
 }
 
-void AudioContext::uninitializeDispatch(void* userData)
+void AudioContext::stopDispatch(void* userData)
 {
     AudioContext* context = reinterpret_cast<AudioContext*>(userData);
     ASSERT(context);
@@ -291,17 +309,23 @@
         return;
 
     context->uninitialize();
+    context->clear();
 }
 
 void AudioContext::stop()
 {
     m_document = 0; // document is going away
 
+    // Usually ScriptExecutionContext calls stop twice.
+    if (m_isStopScheduled)
+        return;
+    m_isStopScheduled = true;
+
     // Don't call uninitialize() immediately here because the ScriptExecutionContext is in the middle
     // of dealing with all of its ActiveDOMObjects at this point. uninitialize() can de-reference other
     // ActiveDOMObjects so let's schedule uninitialize() to be called later.
     // FIXME: see if there's a more direct way to handle this issue.
-    callOnMainThread(uninitializeDispatch, this);
+    callOnMainThread(stopDispatch, this);
 }
 
 Document* AudioContext::document() const
@@ -770,8 +794,12 @@
 void AudioContext::markForDeletion(AudioNode* node)
 {
     ASSERT(isGraphOwner());
-    m_nodesMarkedForDeletion.append(node);
 
+    if (isAudioThreadFinished())
+        m_nodesToDelete.append(node);
+    else
+        m_nodesMarkedForDeletion.append(node);
+
     // This is probably the best time for us to remove the node from automatic pull list,
     // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks()
     // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to
@@ -788,8 +816,7 @@
 
     // Make sure to call deleteMarkedNodes() on main thread.    
     if (m_nodesMarkedForDeletion.size() && !m_isDeletionScheduled) {
-        for (unsigned i = 0; i < m_nodesMarkedForDeletion.size(); ++i)
-            m_nodesToDelete.append(m_nodesMarkedForDeletion[i]);
+        m_nodesToDelete.append(m_nodesMarkedForDeletion);
         m_nodesMarkedForDeletion.clear();
 
         m_isDeletionScheduled = true;
@@ -816,27 +843,30 @@
 {
     ASSERT(isMainThread());
 
-    AutoLocker locker(this);
-    
-    while (size_t n = m_nodesToDelete.size()) {
-        AudioNode* node = m_nodesToDelete[n - 1];
-        m_nodesToDelete.removeLast();
+    // Protect this object from being deleted before we release the mutex locked by AutoLocker.
+    RefPtr<AudioContext> protect(this);
+    {
+        AutoLocker locker(this);
 
-        // Before deleting the node, clear out any AudioNodeInputs from m_dirtySummingJunctions.
-        unsigned numberOfInputs = node->numberOfInputs();
-        for (unsigned i = 0; i < numberOfInputs; ++i)
-            m_dirtySummingJunctions.remove(node->input(i));
+        while (size_t n = m_nodesToDelete.size()) {
+            AudioNode* node = m_nodesToDelete[n - 1];
+            m_nodesToDelete.removeLast();
 
-        // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
-        unsigned numberOfOutputs = node->numberOfOutputs();
-        for (unsigned i = 0; i < numberOfOutputs; ++i)
-            m_dirtyAudioNodeOutputs.remove(node->output(i));
+            // Before deleting the node, clear out any AudioNodeInputs from m_dirtySummingJunctions.
+            unsigned numberOfInputs = node->numberOfInputs();
+            for (unsigned i = 0; i < numberOfInputs; ++i)
+                m_dirtySummingJunctions.remove(node->input(i));
 
-        // Finally, delete it.
-        delete node;
+            // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
+            unsigned numberOfOutputs = node->numberOfOutputs();
+            for (unsigned i = 0; i < numberOfOutputs; ++i)
+                m_dirtyAudioNodeOutputs.remove(node->output(i));
+
+            // Finally, delete it.
+            delete node;
+        }
+        m_isDeletionScheduled = false;
     }
-    
-    m_isDeletionScheduled = false;
 }
 
 void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunction)

Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.h (135151 => 135152)


--- trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2012-11-19 14:53:38 UTC (rev 135152)
@@ -255,8 +255,13 @@
 
     void lazyInitialize();
     void uninitialize();
-    static void uninitializeDispatch(void* userData);
 
+    // ScriptExecutionContext calls stop twice.
+    // We'd like to schedule only one stop action for them.
+    bool m_isStopScheduled;
+    static void stopDispatch(void* userData);
+    void clear();
+
     void scheduleNodeDeletion();
     static void deleteMarkedNodesDispatch(void* userData);
     

Modified: trunk/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp (135151 => 135152)


--- trunk/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp	2012-11-19 14:53:38 UTC (rev 135152)
@@ -91,10 +91,10 @@
         return throwError(v8SyntaxError, "Error creating AudioContext", args.GetIsolate());
     
     // Transform the holder into a wrapper object for the audio context.
-    V8DOMWrapper::setDOMWrapper(args.Holder(), &info, audioContext.get());
-    audioContext->ref();
+    v8::Handle<v8::Object> wrapper = args.Holder();
+    V8DOMWrapper::createDOMWrapper(audioContext.release(), &info, wrapper);
     
-    return args.Holder();
+    return wrapper;
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp (135151 => 135152)


--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2012-11-19 14:53:38 UTC (rev 135152)
@@ -536,6 +536,8 @@
     reportRenderTreeInfo(memoryInstrumentationClient, m_page);
     collectDomTreeInfo(memoryInstrumentation, m_page); // FIXME: collect for all pages?
 
+    PlatformMemoryInstrumentation::reportMemoryUsage(&memoryInstrumentation);
+
     RefPtr<InspectorMemoryBlocks> children = InspectorMemoryBlocks::create();
     addPlatformComponentsInfo(children);
 

Modified: trunk/Source/WebCore/platform/PlatformMemoryInstrumentation.cpp (135151 => 135152)


--- trunk/Source/WebCore/platform/PlatformMemoryInstrumentation.cpp	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/Source/WebCore/platform/PlatformMemoryInstrumentation.cpp	2012-11-19 14:53:38 UTC (rev 135152)
@@ -31,6 +31,10 @@
 #include "config.h"
 #include "PlatformMemoryInstrumentation.h"
 
+#if ENABLE(WEB_AUDIO)
+#include "HRTFDatabaseLoader.h"
+#endif
+
 namespace WebCore {
 
 MemoryObjectType PlatformMemoryTypes::Image = "Page.Image";
@@ -39,4 +43,13 @@
 MemoryObjectType PlatformMemoryTypes::Audio = "Page.Audio";
 MemoryObjectType PlatformMemoryTypes::AudioSharedData = "Page.Audio.SharedData";
 
+void PlatformMemoryInstrumentation::reportMemoryUsage(WTF::MemoryInstrumentation* memoryInstrumentation)
+{
+#if ENABLE(WEB_AUDIO)
+    memoryInstrumentation->addRootObject(HRTFDatabaseLoader::loader());
+#else
+    UNUSED_PARAM(memoryInstrumentation);
+#endif
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/PlatformMemoryInstrumentation.h (135151 => 135152)


--- trunk/Source/WebCore/platform/PlatformMemoryInstrumentation.h	2012-11-19 14:50:40 UTC (rev 135151)
+++ trunk/Source/WebCore/platform/PlatformMemoryInstrumentation.h	2012-11-19 14:53:38 UTC (rev 135152)
@@ -48,6 +48,11 @@
     static MemoryObjectType AudioSharedData;
 };
 
+class PlatformMemoryInstrumentation {
+public:
+    static void reportMemoryUsage(WTF::MemoryInstrumentation*);
+};
+
 } // namespace WebCore
 
 #endif // !defined(PlatformMemoryInstrumentation_h)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to