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

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: addressed 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 class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObser ver {
37 namespace { 40 WTF_MAKE_FAST_ALLOCATED;
38 unsigned totalAsyncCallStacks = 0; 41 public:
39 } 42 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu tionContext)
40 #endif 43 : ContextLifecycleObserver(executionContext)
44 , m_tracker(tracker)
45 {
46 }
47
48 virtual void contextDestroyed() OVERRIDE
49 {
50 ContextLifecycleObserver::contextDestroyed();
51 m_tracker->contextDestroyed(executionContext());
52 }
53
54 private:
55 friend class AsyncCallStackTracker;
56 AsyncCallStackTracker* m_tracker;
57 HashSet<int> m_intervalTimerIds;
58 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains;
59 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains;
60 };
41 61
42 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const ScriptValue& callFra mes) 62 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const ScriptValue& callFra mes)
43 : m_callFrames(callFrames) 63 : m_callFrames(callFrames)
44 { 64 {
45 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT
46 fprintf(stderr, "AsyncCallStack::AsyncCallStack() %u\n", ++totalAsyncCallSta cks);
47 #endif
48 } 65 }
49 66
50 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() 67 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack()
51 { 68 {
52 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT
53 fprintf(stderr, "AsyncCallStack::~AsyncCallStack() %u\n", --totalAsyncCallSt acks);
54 #endif
55 } 69 }
56 70
57 AsyncCallStackTracker::AsyncCallStackTracker() 71 AsyncCallStackTracker::AsyncCallStackTracker()
58 : m_maxAsyncCallStackDepth(0) 72 : m_maxAsyncCallStackDepth(0)
59 { 73 {
60 #ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT
61 m_maxAsyncCallStackDepth = 4;
62 #endif
63 } 74 }
64 75
65 void AsyncCallStackTracker::setAsyncCallStackDepth(int depth) 76 void AsyncCallStackTracker::setAsyncCallStackDepth(int depth)
66 { 77 {
67 if (depth <= 0) { 78 if (depth <= 0) {
68 m_maxAsyncCallStackDepth = 0; 79 m_maxAsyncCallStackDepth = 0;
69 clear(); 80 clear();
70 } else { 81 } else {
71 m_maxAsyncCallStackDepth = depth; 82 m_maxAsyncCallStackDepth = depth;
72 } 83 }
73 } 84 }
74 85
75 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync CallChain() const 86 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync CallChain() const
76 { 87 {
77 if (m_currentAsyncCallChain) 88 if (m_currentAsyncCallChain)
78 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa llStackDepth); 89 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa llStackDepth);
79 return m_currentAsyncCallChain.get(); 90 return m_currentAsyncCallChain.get();
80 } 91 }
81 92
82 void AsyncCallStackTracker::didInstallTimer(int timerId, bool singleShot, const ScriptValue& callFrames) 93 void AsyncCallStackTracker::didInstallTimer(ExecutionContext* context, int timer Id, bool singleShot, const ScriptValue& callFrames)
83 { 94 {
84 ASSERT(isEnabled()); 95 ASSERT(isEnabled());
85 if (!validateCallFrames(callFrames)) 96 if (!validateCallFrames(callFrames))
86 return; 97 return;
87 ASSERT(timerId > 0); 98 ASSERT(timerId > 0);
88 m_timerCallChains.set(timerId, createAsyncCallChain(callFrames)); 99 ExecutionContextData* data = createContextDataIfNeeded(context);
100 data->m_timerCallChains.set(timerId, createAsyncCallChain(callFrames));
89 if (!singleShot) 101 if (!singleShot)
90 m_intervalTimerIds.add(timerId); 102 data->m_intervalTimerIds.add(timerId);
91 } 103 }
92 104
93 void AsyncCallStackTracker::didRemoveTimer(int timerId) 105 void AsyncCallStackTracker::didRemoveTimer(ExecutionContext* context, int timerI d)
94 { 106 {
95 if (!isEnabled() || timerId <= 0) 107 if (!isEnabled() || timerId <= 0)
96 return; 108 return;
97 m_intervalTimerIds.remove(timerId); 109 ExecutionContextData* data = m_executionContextDataMap.get(context);
98 m_timerCallChains.remove(timerId); 110 if (!data)
111 return;
112 data->m_intervalTimerIds.remove(timerId);
113 data->m_timerCallChains.remove(timerId);
99 } 114 }
100 115
101 void AsyncCallStackTracker::willFireTimer(int timerId) 116 void AsyncCallStackTracker::willFireTimer(ExecutionContext* context, int timerId )
102 { 117 {
103 if (!isEnabled()) 118 if (!isEnabled())
104 return; 119 return;
105 ASSERT(timerId > 0); 120 ASSERT(timerId > 0);
106 ASSERT(!m_currentAsyncCallChain); 121 ASSERT(!m_currentAsyncCallChain);
107 if (m_intervalTimerIds.contains(timerId)) 122 ExecutionContextData* data = m_executionContextDataMap.get(context);
108 m_currentAsyncCallChain = m_timerCallChains.get(timerId); 123 if (!data)
124 return;
125 if (data->m_intervalTimerIds.contains(timerId))
126 m_currentAsyncCallChain = data->m_timerCallChains.get(timerId);
109 else 127 else
110 m_currentAsyncCallChain = m_timerCallChains.take(timerId); 128 m_currentAsyncCallChain = data->m_timerCallChains.take(timerId);
111 } 129 }
112 130
113 void AsyncCallStackTracker::didRequestAnimationFrame(int callbackId, const Scrip tValue& callFrames) 131 void AsyncCallStackTracker::didRequestAnimationFrame(ExecutionContext* context, int callbackId, const ScriptValue& callFrames)
114 { 132 {
115 ASSERT(isEnabled()); 133 ASSERT(isEnabled());
116 if (!validateCallFrames(callFrames)) 134 if (!validateCallFrames(callFrames))
117 return; 135 return;
118 ASSERT(callbackId > 0); 136 ASSERT(callbackId > 0);
119 m_animationFrameCallChains.set(callbackId, createAsyncCallChain(callFrames)) ; 137 ExecutionContextData* data = createContextDataIfNeeded(context);
138 data->m_animationFrameCallChains.set(callbackId, createAsyncCallChain(callFr ames));
120 } 139 }
121 140
122 void AsyncCallStackTracker::didCancelAnimationFrame(int callbackId) 141 void AsyncCallStackTracker::didCancelAnimationFrame(ExecutionContext* context, i nt callbackId)
123 { 142 {
124 if (!isEnabled() || callbackId <= 0) 143 if (!isEnabled() || callbackId <= 0)
125 return; 144 return;
126 m_animationFrameCallChains.remove(callbackId); 145 ExecutionContextData* data = m_executionContextDataMap.get(context);
146 if (!data)
147 return;
148 data->m_animationFrameCallChains.remove(callbackId);
127 } 149 }
128 150
129 void AsyncCallStackTracker::willFireAnimationFrame(int callbackId) 151 void AsyncCallStackTracker::willFireAnimationFrame(ExecutionContext* context, in t callbackId)
130 { 152 {
131 if (!isEnabled()) 153 if (!isEnabled())
132 return; 154 return;
133 ASSERT(callbackId > 0); 155 ASSERT(callbackId > 0);
134 ASSERT(!m_currentAsyncCallChain); 156 ASSERT(!m_currentAsyncCallChain);
135 m_currentAsyncCallChain = m_animationFrameCallChains.take(callbackId); 157 ExecutionContextData* data = m_executionContextDataMap.get(context);
158 if (!data)
159 return;
160 m_currentAsyncCallChain = data->m_animationFrameCallChains.take(callbackId);
136 } 161 }
137 162
138 void AsyncCallStackTracker::didFireAsyncCall() 163 void AsyncCallStackTracker::didFireAsyncCall()
139 { 164 {
140 m_currentAsyncCallChain = 0; 165 m_currentAsyncCallChain = 0;
141 } 166 }
142 167
143 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const ScriptValue& callFrames) 168 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const ScriptValue& callFrames)
144 { 169 {
145 ASSERT(isEnabled()); 170 ASSERT(isEnabled());
146 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain()); 171 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain());
147 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); 172 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1);
148 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta ck(callFrames))); 173 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta ck(callFrames)));
149 return chain.release(); 174 return chain.release();
150 } 175 }
151 176
152 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain, unsigned maxDepth) 177 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain, unsigned maxDepth)
153 { 178 {
154 while (chain->m_callStacks.size() > maxDepth) 179 while (chain->m_callStacks.size() > maxDepth)
155 chain->m_callStacks.removeLast(); 180 chain->m_callStacks.removeLast();
156 } 181 }
157 182
158 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) 183 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames)
159 { 184 {
160 return !callFrames.hasNoValue() && callFrames.isObject(); 185 return !callFrames.hasNoValue() && callFrames.isObject();
161 } 186 }
162 187
188 void AsyncCallStackTracker::contextDestroyed(ExecutionContext* context)
189 {
190 ExecutionContextData* data = m_executionContextDataMap.take(context);
191 if (data)
192 delete data;
193 }
194
195 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex tDataIfNeeded(ExecutionContext* context)
196 {
197 ExecutionContextData* data = m_executionContextDataMap.get(context);
198 if (!data) {
199 data = new AsyncCallStackTracker::ExecutionContextData(this, context);
200 m_executionContextDataMap.set(context, data);
201 }
202 return data;
203 }
204
163 void AsyncCallStackTracker::clear() 205 void AsyncCallStackTracker::clear()
164 { 206 {
165 m_currentAsyncCallChain = 0; 207 m_currentAsyncCallChain = 0;
166 m_intervalTimerIds.clear(); 208 Vector<ExecutionContextData*> contextsData;
167 m_timerCallChains.clear(); 209 copyValuesToVector(m_executionContextDataMap, contextsData);
168 m_animationFrameCallChains.clear(); 210 m_executionContextDataMap.clear();
211 for (Vector<ExecutionContextData*>::const_iterator it = contextsData.begin() ; it != contextsData.end(); ++it)
212 delete *it;
169 } 213 }
170 214
171 } // namespace WebCore 215 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/inspector/AsyncCallStackTracker.h ('k') | Source/core/inspector/InspectorDebuggerAgent.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698