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

Side by Side Diff: Source/core/inspector/AsyncCallStackTracker.cpp

Issue 111653002: DevTools: Track async stacks on the corresponding execution context. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: no RefCounted Created 7 years 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) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 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 are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/inspector/AsyncCallStackTracker.h" 32 #include "core/inspector/AsyncCallStackTracker.h"
33 33
34 #include "core/dom/ContextLifecycleObserver.h"
35 #include "core/dom/ExecutionContext.h"
36
34 namespace WebCore { 37 namespace WebCore {
35 38
36 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT 39 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT
37 namespace { 40 namespace {
38 unsigned totalAsyncCallStacks = 0; 41 unsigned totalAsyncCallStacks = 0;
42 unsigned totalExecutionContextData = 0;
39 } 43 }
40 #endif 44 #endif
41 45
46 class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObser ver {
47 WTF_MAKE_FAST_ALLOCATED;
48 public:
49 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu tionContext)
50 : ContextLifecycleObserver(executionContext)
51 , m_tracker(tracker)
52 {
53 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT
pfeldman 2013/12/10 15:45:02 remove
54 fprintf(stderr, "ExecutionContextData::ExecutionContextData() %u\n", ++t otalExecutionContextData);
55 #endif
56 }
57
58 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT
59 virtual ~ExecutionContextData()
60 {
61 fprintf(stderr, "ExecutionContextData::~ExecutionContextData() %u\n", -- totalExecutionContextData);
62 }
63 #endif
64
65 virtual void contextDestroyed() OVERRIDE
66 {
67 ContextLifecycleObserver::contextDestroyed();
68 m_tracker->contextDestroyed(executionContext());
69 }
70
71 private:
72 friend class AsyncCallStackTracker;
73 AsyncCallStackTracker* m_tracker;
74 HashSet<int> m_intervalTimerIds;
75 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains;
76 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains;
77 };
78
42 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const ScriptValue& callFra mes) 79 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const ScriptValue& callFra mes)
43 : m_callFrames(callFrames) 80 : m_callFrames(callFrames)
44 { 81 {
45 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT 82 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT
46 fprintf(stderr, "AsyncCallStack::AsyncCallStack() %u\n", ++totalAsyncCallSta cks); 83 fprintf(stderr, "AsyncCallStack::AsyncCallStack() %u\n", ++totalAsyncCallSta cks);
47 #endif 84 #endif
48 } 85 }
49 86
50 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() 87 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack()
51 { 88 {
(...skipping 20 matching lines...) Expand all
72 } 109 }
73 } 110 }
74 111
75 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync CallChain() const 112 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync CallChain() const
76 { 113 {
77 if (m_currentAsyncCallChain) 114 if (m_currentAsyncCallChain)
78 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa llStackDepth); 115 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa llStackDepth);
79 return m_currentAsyncCallChain.get(); 116 return m_currentAsyncCallChain.get();
80 } 117 }
81 118
82 void AsyncCallStackTracker::didInstallTimer(int timerId, bool singleShot, const ScriptValue& callFrames) 119 void AsyncCallStackTracker::didInstallTimer(ExecutionContext* context, int timer Id, bool singleShot, const ScriptValue& callFrames)
83 { 120 {
84 ASSERT(isEnabled()); 121 ASSERT(isEnabled());
85 if (!validateCallFrames(callFrames)) 122 if (!validateCallFrames(callFrames))
86 return; 123 return;
87 ASSERT(timerId > 0); 124 ASSERT(timerId > 0);
88 m_timerCallChains.set(timerId, createAsyncCallChain(callFrames)); 125 ExecutionContextData* data = createContextDataIfNeeded(context);
126 data->m_timerCallChains.set(timerId, createAsyncCallChain(callFrames));
89 if (!singleShot) 127 if (!singleShot)
90 m_intervalTimerIds.add(timerId); 128 data->m_intervalTimerIds.add(timerId);
91 } 129 }
92 130
93 void AsyncCallStackTracker::didRemoveTimer(int timerId) 131 void AsyncCallStackTracker::didRemoveTimer(ExecutionContext* context, int timerI d)
94 { 132 {
95 if (!isEnabled() || timerId <= 0) 133 if (!isEnabled() || timerId <= 0)
96 return; 134 return;
97 m_intervalTimerIds.remove(timerId); 135 ExecutionContextData* data = m_executionContextDataMap.get(context);
98 m_timerCallChains.remove(timerId); 136 if (!data)
137 return;
138 data->m_intervalTimerIds.remove(timerId);
139 data->m_timerCallChains.remove(timerId);
99 } 140 }
100 141
101 void AsyncCallStackTracker::willFireTimer(int timerId) 142 void AsyncCallStackTracker::willFireTimer(ExecutionContext* context, int timerId )
102 { 143 {
103 if (!isEnabled()) 144 if (!isEnabled())
104 return; 145 return;
105 ASSERT(timerId > 0); 146 ASSERT(timerId > 0);
106 ASSERT(!m_currentAsyncCallChain); 147 ASSERT(!m_currentAsyncCallChain);
107 if (m_intervalTimerIds.contains(timerId)) 148 ExecutionContextData* data = m_executionContextDataMap.get(context);
108 m_currentAsyncCallChain = m_timerCallChains.get(timerId); 149 if (!data)
150 return;
151 if (data->m_intervalTimerIds.contains(timerId))
152 m_currentAsyncCallChain = data->m_timerCallChains.get(timerId);
109 else 153 else
110 m_currentAsyncCallChain = m_timerCallChains.take(timerId); 154 m_currentAsyncCallChain = data->m_timerCallChains.take(timerId);
111 } 155 }
112 156
113 void AsyncCallStackTracker::didRequestAnimationFrame(int callbackId, const Scrip tValue& callFrames) 157 void AsyncCallStackTracker::didRequestAnimationFrame(ExecutionContext* context, int callbackId, const ScriptValue& callFrames)
114 { 158 {
115 ASSERT(isEnabled()); 159 ASSERT(isEnabled());
116 if (!validateCallFrames(callFrames)) 160 if (!validateCallFrames(callFrames))
117 return; 161 return;
118 ASSERT(callbackId > 0); 162 ASSERT(callbackId > 0);
119 m_animationFrameCallChains.set(callbackId, createAsyncCallChain(callFrames)) ; 163 ExecutionContextData* data = createContextDataIfNeeded(context);
164 data->m_animationFrameCallChains.set(callbackId, createAsyncCallChain(callFr ames));
120 } 165 }
121 166
122 void AsyncCallStackTracker::didCancelAnimationFrame(int callbackId) 167 void AsyncCallStackTracker::didCancelAnimationFrame(ExecutionContext* context, i nt callbackId)
123 { 168 {
124 if (!isEnabled() || callbackId <= 0) 169 if (!isEnabled() || callbackId <= 0)
125 return; 170 return;
126 m_animationFrameCallChains.remove(callbackId); 171 ExecutionContextData* data = m_executionContextDataMap.get(context);
172 if (!data)
173 return;
174 data->m_animationFrameCallChains.remove(callbackId);
127 } 175 }
128 176
129 void AsyncCallStackTracker::willFireAnimationFrame(int callbackId) 177 void AsyncCallStackTracker::willFireAnimationFrame(ExecutionContext* context, in t callbackId)
130 { 178 {
131 if (!isEnabled()) 179 if (!isEnabled())
132 return; 180 return;
133 ASSERT(callbackId > 0); 181 ASSERT(callbackId > 0);
134 ASSERT(!m_currentAsyncCallChain); 182 ASSERT(!m_currentAsyncCallChain);
135 m_currentAsyncCallChain = m_animationFrameCallChains.take(callbackId); 183 ExecutionContextData* data = m_executionContextDataMap.get(context);
184 if (!data)
185 return;
186 m_currentAsyncCallChain = data->m_animationFrameCallChains.take(callbackId);
136 } 187 }
137 188
138 void AsyncCallStackTracker::didFireAsyncCall() 189 void AsyncCallStackTracker::didFireAsyncCall()
139 { 190 {
140 m_currentAsyncCallChain = 0; 191 m_currentAsyncCallChain = 0;
141 } 192 }
142 193
143 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const ScriptValue& callFrames) 194 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const ScriptValue& callFrames)
144 { 195 {
145 ASSERT(isEnabled()); 196 ASSERT(isEnabled());
146 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain()); 197 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain());
147 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); 198 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1);
148 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta ck(callFrames))); 199 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta ck(callFrames)));
149 return chain.release(); 200 return chain.release();
150 } 201 }
151 202
152 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain, unsigned maxDepth) 203 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain, unsigned maxDepth)
153 { 204 {
154 while (chain->m_callStacks.size() > maxDepth) 205 while (chain->m_callStacks.size() > maxDepth)
155 chain->m_callStacks.removeLast(); 206 chain->m_callStacks.removeLast();
156 } 207 }
157 208
158 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) 209 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames)
159 { 210 {
160 return !callFrames.hasNoValue() && callFrames.isObject(); 211 return !callFrames.hasNoValue() && callFrames.isObject();
161 } 212 }
162 213
214 void AsyncCallStackTracker::contextDestroyed(ExecutionContext* context)
215 {
216 ExecutionContextData* data = m_executionContextDataMap.take(context);
217 if (data)
218 delete data;
219 }
220
221 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex tDataIfNeeded(ExecutionContext* context)
222 {
223 ExecutionContextData* data = m_executionContextDataMap.get(context);
224 if (!data) {
225 data = new AsyncCallStackTracker::ExecutionContextData(this, context);
226 m_executionContextDataMap.set(context, data);
227 }
228 return data;
229 }
230
163 void AsyncCallStackTracker::clear() 231 void AsyncCallStackTracker::clear()
164 { 232 {
165 m_currentAsyncCallChain = 0; 233 m_currentAsyncCallChain = 0;
166 m_intervalTimerIds.clear(); 234 Vector<ExecutionContextData*> contextsData;
167 m_timerCallChains.clear(); 235 copyValuesToVector(m_executionContextDataMap, contextsData);
168 m_animationFrameCallChains.clear(); 236 m_executionContextDataMap.clear();
237 for (Vector<ExecutionContextData*>::const_iterator it = contextsData.begin() ; it != contextsData.end(); ++it)
238 delete *it;
169 } 239 }
170 240
171 } // namespace WebCore 241 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698