Index: Source/core/inspector/AsyncCallStackTracker.cpp |
diff --git a/Source/core/inspector/AsyncCallStackTracker.cpp b/Source/core/inspector/AsyncCallStackTracker.cpp |
index 0e68ba6bcc381de881bbe2941e7c451e652d7d72..1ae426fe2521812f8db03b9cb7f29c84ef34a2aa 100644 |
--- a/Source/core/inspector/AsyncCallStackTracker.cpp |
+++ b/Source/core/inspector/AsyncCallStackTracker.cpp |
@@ -31,14 +31,51 @@ |
#include "config.h" |
#include "core/inspector/AsyncCallStackTracker.h" |
+#include "core/dom/ContextLifecycleObserver.h" |
+#include "core/dom/ExecutionContext.h" |
+ |
namespace WebCore { |
#ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT |
namespace { |
unsigned totalAsyncCallStacks = 0; |
+unsigned totalExecutionContextData = 0; |
} |
#endif |
+class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObserver { |
+ WTF_MAKE_FAST_ALLOCATED; |
+public: |
+ ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* executionContext) |
+ : ContextLifecycleObserver(executionContext) |
+ , m_tracker(tracker) |
+ { |
+#ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT |
pfeldman
2013/12/10 15:45:02
remove
|
+ fprintf(stderr, "ExecutionContextData::ExecutionContextData() %u\n", ++totalExecutionContextData); |
+#endif |
+ } |
+ |
+#ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT |
+ virtual ~ExecutionContextData() |
+ { |
+ fprintf(stderr, "ExecutionContextData::~ExecutionContextData() %u\n", --totalExecutionContextData); |
+ } |
+#endif |
+ |
+ virtual void contextDestroyed() OVERRIDE |
+ { |
+ ContextLifecycleObserver::contextDestroyed(); |
+ m_tracker->contextDestroyed(executionContext()); |
+ } |
+ |
+private: |
+ friend class AsyncCallStackTracker; |
+ AsyncCallStackTracker* m_tracker; |
+ HashSet<int> m_intervalTimerIds; |
+ HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains; |
+ HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains; |
+}; |
+ |
AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const ScriptValue& callFrames) |
: m_callFrames(callFrames) |
{ |
@@ -79,60 +116,74 @@ const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync |
return m_currentAsyncCallChain.get(); |
} |
-void AsyncCallStackTracker::didInstallTimer(int timerId, bool singleShot, const ScriptValue& callFrames) |
+void AsyncCallStackTracker::didInstallTimer(ExecutionContext* context, int timerId, bool singleShot, const ScriptValue& callFrames) |
{ |
ASSERT(isEnabled()); |
if (!validateCallFrames(callFrames)) |
return; |
ASSERT(timerId > 0); |
- m_timerCallChains.set(timerId, createAsyncCallChain(callFrames)); |
+ ExecutionContextData* data = createContextDataIfNeeded(context); |
+ data->m_timerCallChains.set(timerId, createAsyncCallChain(callFrames)); |
if (!singleShot) |
- m_intervalTimerIds.add(timerId); |
+ data->m_intervalTimerIds.add(timerId); |
} |
-void AsyncCallStackTracker::didRemoveTimer(int timerId) |
+void AsyncCallStackTracker::didRemoveTimer(ExecutionContext* context, int timerId) |
{ |
if (!isEnabled() || timerId <= 0) |
return; |
- m_intervalTimerIds.remove(timerId); |
- m_timerCallChains.remove(timerId); |
+ ExecutionContextData* data = m_executionContextDataMap.get(context); |
+ if (!data) |
+ return; |
+ data->m_intervalTimerIds.remove(timerId); |
+ data->m_timerCallChains.remove(timerId); |
} |
-void AsyncCallStackTracker::willFireTimer(int timerId) |
+void AsyncCallStackTracker::willFireTimer(ExecutionContext* context, int timerId) |
{ |
if (!isEnabled()) |
return; |
ASSERT(timerId > 0); |
ASSERT(!m_currentAsyncCallChain); |
- if (m_intervalTimerIds.contains(timerId)) |
- m_currentAsyncCallChain = m_timerCallChains.get(timerId); |
+ ExecutionContextData* data = m_executionContextDataMap.get(context); |
+ if (!data) |
+ return; |
+ if (data->m_intervalTimerIds.contains(timerId)) |
+ m_currentAsyncCallChain = data->m_timerCallChains.get(timerId); |
else |
- m_currentAsyncCallChain = m_timerCallChains.take(timerId); |
+ m_currentAsyncCallChain = data->m_timerCallChains.take(timerId); |
} |
-void AsyncCallStackTracker::didRequestAnimationFrame(int callbackId, const ScriptValue& callFrames) |
+void AsyncCallStackTracker::didRequestAnimationFrame(ExecutionContext* context, int callbackId, const ScriptValue& callFrames) |
{ |
ASSERT(isEnabled()); |
if (!validateCallFrames(callFrames)) |
return; |
ASSERT(callbackId > 0); |
- m_animationFrameCallChains.set(callbackId, createAsyncCallChain(callFrames)); |
+ ExecutionContextData* data = createContextDataIfNeeded(context); |
+ data->m_animationFrameCallChains.set(callbackId, createAsyncCallChain(callFrames)); |
} |
-void AsyncCallStackTracker::didCancelAnimationFrame(int callbackId) |
+void AsyncCallStackTracker::didCancelAnimationFrame(ExecutionContext* context, int callbackId) |
{ |
if (!isEnabled() || callbackId <= 0) |
return; |
- m_animationFrameCallChains.remove(callbackId); |
+ ExecutionContextData* data = m_executionContextDataMap.get(context); |
+ if (!data) |
+ return; |
+ data->m_animationFrameCallChains.remove(callbackId); |
} |
-void AsyncCallStackTracker::willFireAnimationFrame(int callbackId) |
+void AsyncCallStackTracker::willFireAnimationFrame(ExecutionContext* context, int callbackId) |
{ |
if (!isEnabled()) |
return; |
ASSERT(callbackId > 0); |
ASSERT(!m_currentAsyncCallChain); |
- m_currentAsyncCallChain = m_animationFrameCallChains.take(callbackId); |
+ ExecutionContextData* data = m_executionContextDataMap.get(context); |
+ if (!data) |
+ return; |
+ m_currentAsyncCallChain = data->m_animationFrameCallChains.take(callbackId); |
} |
void AsyncCallStackTracker::didFireAsyncCall() |
@@ -160,12 +211,31 @@ bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) |
return !callFrames.hasNoValue() && callFrames.isObject(); |
} |
+void AsyncCallStackTracker::contextDestroyed(ExecutionContext* context) |
+{ |
+ ExecutionContextData* data = m_executionContextDataMap.take(context); |
+ if (data) |
+ delete data; |
+} |
+ |
+AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContextDataIfNeeded(ExecutionContext* context) |
+{ |
+ ExecutionContextData* data = m_executionContextDataMap.get(context); |
+ if (!data) { |
+ data = new AsyncCallStackTracker::ExecutionContextData(this, context); |
+ m_executionContextDataMap.set(context, data); |
+ } |
+ return data; |
+} |
+ |
void AsyncCallStackTracker::clear() |
{ |
m_currentAsyncCallChain = 0; |
- m_intervalTimerIds.clear(); |
- m_timerCallChains.clear(); |
- m_animationFrameCallChains.clear(); |
+ Vector<ExecutionContextData*> contextsData; |
+ copyValuesToVector(m_executionContextDataMap, contextsData); |
+ m_executionContextDataMap.clear(); |
+ for (Vector<ExecutionContextData*>::const_iterator it = contextsData.begin(); it != contextsData.end(); ++it) |
+ delete *it; |
} |
} // namespace WebCore |