Index: Source/core/inspector/AsyncCallStackTracker.cpp |
diff --git a/Source/core/inspector/AsyncCallStackTracker.cpp b/Source/core/inspector/AsyncCallStackTracker.cpp |
index 0e68ba6bcc381de881bbe2941e7c451e652d7d72..f7b4003b0f3b94c1a92fe1f1468977465f98cd38 100644 |
--- a/Source/core/inspector/AsyncCallStackTracker.cpp |
+++ b/Source/core/inspector/AsyncCallStackTracker.cpp |
@@ -31,35 +31,46 @@ |
#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; |
-} |
-#endif |
+class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObserver { |
+ WTF_MAKE_FAST_ALLOCATED; |
+public: |
+ ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* executionContext) |
+ : ContextLifecycleObserver(executionContext) |
+ , m_tracker(tracker) |
+ { |
+ } |
+ |
+ 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) |
{ |
-#ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT |
- fprintf(stderr, "AsyncCallStack::AsyncCallStack() %u\n", ++totalAsyncCallStacks); |
-#endif |
} |
AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() |
{ |
-#ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT |
- fprintf(stderr, "AsyncCallStack::~AsyncCallStack() %u\n", --totalAsyncCallStacks); |
-#endif |
} |
AsyncCallStackTracker::AsyncCallStackTracker() |
: m_maxAsyncCallStackDepth(0) |
{ |
-#ifdef DEBUG_ASYNC_CALLS_DEBUGGER_SUPPORT |
- m_maxAsyncCallStackDepth = 4; |
-#endif |
} |
void AsyncCallStackTracker::setAsyncCallStackDepth(int depth) |
@@ -79,60 +90,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 +185,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 |