Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: Source/modules/webaudio/AudioContext.cpp

Issue 802593004: WebAudio: Fix AudioNode leak in a case that AudioNode is not disconnected from the graph explicitly. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010, Google Inc. All rights reserved. 2 * Copyright (C) 2010, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 : ActiveDOMObject(document) 104 : ActiveDOMObject(document)
105 , m_isStopScheduled(false) 105 , m_isStopScheduled(false)
106 , m_isCleared(false) 106 , m_isCleared(false)
107 , m_isInitialized(false) 107 , m_isInitialized(false)
108 , m_destinationNode(nullptr) 108 , m_destinationNode(nullptr)
109 , m_isResolvingResumePromises(false) 109 , m_isResolvingResumePromises(false)
110 , m_automaticPullNodesNeedUpdating(false) 110 , m_automaticPullNodesNeedUpdating(false)
111 , m_connectionCount(0) 111 , m_connectionCount(0)
112 , m_didInitializeContextGraphMutex(false) 112 , m_didInitializeContextGraphMutex(false)
113 , m_audioThread(0) 113 , m_audioThread(0)
114 , m_lastZombie(nullptr)
115 , m_lastRemovableZombie(nullptr)
114 , m_isOfflineContext(false) 116 , m_isOfflineContext(false)
115 , m_contextState(Suspended) 117 , m_contextState(Suspended)
116 , m_cachedSampleFrame(0) 118 , m_cachedSampleFrame(0)
117 { 119 {
118 m_didInitializeContextGraphMutex = true; 120 m_didInitializeContextGraphMutex = true;
119 m_destinationNode = DefaultAudioDestinationNode::create(this); 121 m_destinationNode = DefaultAudioDestinationNode::create(this);
120 122
121 initialize(); 123 initialize();
122 } 124 }
123 125
124 // Constructor for offline (non-realtime) rendering. 126 // Constructor for offline (non-realtime) rendering.
125 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) 127 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate)
126 : ActiveDOMObject(document) 128 : ActiveDOMObject(document)
127 , m_isStopScheduled(false) 129 , m_isStopScheduled(false)
128 , m_isCleared(false) 130 , m_isCleared(false)
129 , m_isInitialized(false) 131 , m_isInitialized(false)
130 , m_destinationNode(nullptr) 132 , m_destinationNode(nullptr)
131 , m_isResolvingResumePromises(false) 133 , m_isResolvingResumePromises(false)
132 , m_automaticPullNodesNeedUpdating(false) 134 , m_automaticPullNodesNeedUpdating(false)
133 , m_connectionCount(0) 135 , m_connectionCount(0)
134 , m_didInitializeContextGraphMutex(false) 136 , m_didInitializeContextGraphMutex(false)
135 , m_audioThread(0) 137 , m_audioThread(0)
138 , m_lastZombie(nullptr)
139 , m_lastRemovableZombie(nullptr)
136 , m_isOfflineContext(true) 140 , m_isOfflineContext(true)
137 , m_contextState(Suspended) 141 , m_contextState(Suspended)
138 , m_cachedSampleFrame(0) 142 , m_cachedSampleFrame(0)
139 { 143 {
140 m_didInitializeContextGraphMutex = true; 144 m_didInitializeContextGraphMutex = true;
141 // Create a new destination for offline rendering. 145 // Create a new destination for offline rendering.
142 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); 146 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate);
143 if (m_renderTarget.get()) 147 if (m_renderTarget.get())
144 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); 148 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get());
145 149
(...skipping 16 matching lines...) Expand all
162 ASSERT(!m_suspendResolvers.size()); 166 ASSERT(!m_suspendResolvers.size());
163 ASSERT(!m_isResolvingResumePromises); 167 ASSERT(!m_isResolvingResumePromises);
164 ASSERT(!m_resumeResolvers.size()); 168 ASSERT(!m_resumeResolvers.size());
165 } 169 }
166 170
167 void AudioContext::initialize() 171 void AudioContext::initialize()
168 { 172 {
169 if (isInitialized()) 173 if (isInitialized())
170 return; 174 return;
171 175
176 ThreadState::current()->addMarkingTask(this);
172 FFTFrame::initialize(); 177 FFTFrame::initialize();
173 m_listener = AudioListener::create(); 178 m_listener = AudioListener::create();
174 179
175 if (m_destinationNode.get()) { 180 if (m_destinationNode.get()) {
176 m_destinationNode->initialize(); 181 m_destinationNode->initialize();
177 182
178 if (!isOfflineContext()) { 183 if (!isOfflineContext()) {
179 // This starts the audio thread. The destination node's provideInput () method will now be called repeatedly to render audio. 184 // This starts the audio thread. The destination node's provideInput () method will now be called repeatedly to render audio.
180 // Each time provideInput() is called, a portion of the audio stream is rendered. Let's call this time period a "render quantum". 185 // Each time provideInput() is called, a portion of the audio stream is rendered. Let's call this time period a "render quantum".
181 // NOTE: for now default AudioContext does not need an explicit star tRendering() call from JavaScript. 186 // NOTE: for now default AudioContext does not need an explicit star tRendering() call from JavaScript.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 setContextState(Closed); 237 setContextState(Closed);
233 238
234 // Resolve the promise now, if any 239 // Resolve the promise now, if any
235 if (m_closeResolver) 240 if (m_closeResolver)
236 m_closeResolver->resolve(); 241 m_closeResolver->resolve();
237 242
238 ASSERT(m_listener); 243 ASSERT(m_listener);
239 m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); 244 m_listener->waitForHRTFDatabaseLoaderThreadCompletion();
240 245
241 clear(); 246 clear();
247
248 ThreadState::current()->removeMarkingTask(this);
249 if (m_lastZombie)
250 ThreadState::current()->purifyZombies();
251 m_lastZombie = nullptr;
252 m_lastRemovableZombie = nullptr;
242 } 253 }
243 254
244 void AudioContext::stop() 255 void AudioContext::stop()
245 { 256 {
246 // Usually ExecutionContext calls stop twice. 257 // Usually ExecutionContext calls stop twice.
247 if (m_isStopScheduled) 258 if (m_isStopScheduled)
248 return; 259 return;
249 m_isStopScheduled = true; 260 m_isStopScheduled = true;
250 261
251 // Don't call uninitialize() immediately here because the ExecutionContext i s in the middle 262 // Don't call uninitialize() immediately here because the ExecutionContext i s in the middle
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 if (tryLock()) { 989 if (tryLock()) {
979 // Update the channel count mode. 990 // Update the channel count mode.
980 updateChangedChannelCountMode(); 991 updateChangedChannelCountMode();
981 992
982 // Take care of AudioNode tasks where the tryLock() failed previously. 993 // Take care of AudioNode tasks where the tryLock() failed previously.
983 handleDeferredAudioNodeTasks(); 994 handleDeferredAudioNodeTasks();
984 995
985 // Dynamically clean up nodes which are no longer needed. 996 // Dynamically clean up nodes which are no longer needed.
986 derefFinishedSourceNodes(); 997 derefFinishedSourceNodes();
987 998
999 m_lastRemovableZombie = m_lastZombie;
1000
988 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts. 1001 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts.
989 handleDirtyAudioSummingJunctions(); 1002 handleDirtyAudioSummingJunctions();
990 handleDirtyAudioNodeOutputs(); 1003 handleDirtyAudioNodeOutputs();
991 1004
992 updateAutomaticPullNodes(); 1005 updateAutomaticPullNodes();
993 resolvePromisesForSuspend(); 1006 resolvePromisesForSuspend();
994 1007
995 unlock(); 1008 unlock();
996 } 1009 }
997 } 1010 }
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 } 1287 }
1275 } 1288 }
1276 1289
1277 DEFINE_TRACE(AudioContext) 1290 DEFINE_TRACE(AudioContext)
1278 { 1291 {
1279 visitor->trace(m_closeResolver); 1292 visitor->trace(m_closeResolver);
1280 visitor->trace(m_offlineResolver); 1293 visitor->trace(m_offlineResolver);
1281 visitor->trace(m_renderTarget); 1294 visitor->trace(m_renderTarget);
1282 visitor->trace(m_destinationNode); 1295 visitor->trace(m_destinationNode);
1283 visitor->trace(m_listener); 1296 visitor->trace(m_listener);
1284 // trace() can be called in AudioContext constructor, and 1297 visitor->trace(m_referencedNodes);
1285 // m_contextGraphMutex might be unavailable.
1286 if (m_didInitializeContextGraphMutex) {
1287 AutoLocker lock(this);
1288 visitor->trace(m_referencedNodes);
1289 } else {
1290 visitor->trace(m_referencedNodes);
1291 }
1292 visitor->trace(m_resumeResolvers); 1298 visitor->trace(m_resumeResolvers);
1293 visitor->trace(m_suspendResolvers); 1299 visitor->trace(m_suspendResolvers);
1294 visitor->trace(m_liveNodes); 1300 visitor->trace(m_liveNodes);
1295 visitor->trace(m_liveAudioSummingJunctions); 1301 visitor->trace(m_liveAudioSummingJunctions);
1296 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis itor); 1302 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis itor);
1297 ActiveDOMObject::trace(visitor); 1303 ActiveDOMObject::trace(visitor);
1298 } 1304 }
1299 1305
1300 void AudioContext::addChangedChannelCountMode(AudioNode* node) 1306 void AudioContext::addChangedChannelCountMode(AudioNode* node)
1301 { 1307 {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1358 1364
1359 // Stop the audio context. This will stop the destination node from pulling audio anymore. And 1365 // Stop the audio context. This will stop the destination node from pulling audio anymore. And
1360 // since we have disconnected the destination from the audio graph, and thus has no references, 1366 // since we have disconnected the destination from the audio graph, and thus has no references,
1361 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise 1367 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise
1362 // created here. 1368 // created here.
1363 stop(); 1369 stop();
1364 1370
1365 return promise; 1371 return promise;
1366 } 1372 }
1367 1373
1374 void AudioContext::setLastZombie(void* object)
1375 {
1376 ASSERT(isGraphOwner());
1377 m_lastZombie = object;
1378 }
1379
1380 void AudioContext::willStartMarking(ThreadState& threadState)
1381 {
1382 lock();
1383 if (!m_lastRemovableZombie)
1384 return;
1385 if (m_lastZombie != m_lastRemovableZombie)
1386 return;
1387 threadState.purifyZombies();
1388 m_lastZombie = nullptr;
1389 m_lastRemovableZombie = nullptr;
1390 }
1391
1392 void AudioContext::didFinishMarking(ThreadState&)
1393 {
1394 unlock();
1395 }
1396
1368 } // namespace blink 1397 } // namespace blink
1369 1398
1370 #endif // ENABLE(WEB_AUDIO) 1399 #endif // ENABLE(WEB_AUDIO)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698