| OLD | NEW | 
|    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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   54  |   54  | 
|   55 } |   55 } | 
|   56  |   56  | 
|   57 namespace blink { |   57 namespace blink { | 
|   58  |   58  | 
|   59 class AsyncCallStackTracker::ExecutionContextData FINAL : public ContextLifecycl
     eObserver { |   59 class AsyncCallStackTracker::ExecutionContextData FINAL : public ContextLifecycl
     eObserver { | 
|   60     WTF_MAKE_FAST_ALLOCATED; |   60     WTF_MAKE_FAST_ALLOCATED; | 
|   61 public: |   61 public: | 
|   62     ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu
     tionContext) |   62     ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu
     tionContext) | 
|   63         : ContextLifecycleObserver(executionContext) |   63         : ContextLifecycleObserver(executionContext) | 
 |   64         , m_circularSequentialID(0) | 
|   64         , m_tracker(tracker) |   65         , m_tracker(tracker) | 
|   65     { |   66     { | 
|   66     } |   67     } | 
|   67  |   68  | 
|   68     virtual void contextDestroyed() OVERRIDE |   69     virtual void contextDestroyed() OVERRIDE | 
|   69     { |   70     { | 
|   70         ASSERT(executionContext()); |   71         ASSERT(executionContext()); | 
|   71         ExecutionContextData* self = m_tracker->m_executionContextDataMap.take(e
     xecutionContext()); |   72         ExecutionContextData* self = m_tracker->m_executionContextDataMap.take(e
     xecutionContext()); | 
|   72         ASSERT(self == this); |   73         ASSERT(self == this); | 
|   73         ContextLifecycleObserver::contextDestroyed(); |   74         ContextLifecycleObserver::contextDestroyed(); | 
|   74         delete self; |   75         delete self; | 
|   75     } |   76     } | 
|   76  |   77  | 
 |   78     int circularSequentialID() | 
 |   79     { | 
 |   80         ++m_circularSequentialID; | 
 |   81         if (m_circularSequentialID <= 0) | 
 |   82             m_circularSequentialID = 1; | 
 |   83         return m_circularSequentialID; | 
 |   84     } | 
 |   85  | 
 |   86 private: | 
 |   87     int m_circularSequentialID; | 
 |   88  | 
|   77 public: |   89 public: | 
|   78     AsyncCallStackTracker* m_tracker; |   90     AsyncCallStackTracker* m_tracker; | 
|   79     HashSet<int> m_intervalTimerIds; |   91     HashSet<int> m_intervalTimerIds; | 
|   80     HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains; |   92     HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains; | 
|   81     HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains; |   93     HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains; | 
|   82     HashMap<Event*, RefPtr<AsyncCallChain> > m_eventCallChains; |   94     HashMap<Event*, RefPtr<AsyncCallChain> > m_eventCallChains; | 
|   83     HashMap<EventTarget*, RefPtr<AsyncCallChain> > m_xhrCallChains; |   95     HashMap<EventTarget*, RefPtr<AsyncCallChain> > m_xhrCallChains; | 
|   84     HashMap<MutationObserver*, RefPtr<AsyncCallChain> > m_mutationObserverCallCh
     ains; |   96     HashMap<MutationObserver*, RefPtr<AsyncCallChain> > m_mutationObserverCallCh
     ains; | 
|   85     HashMap<ExecutionContextTask*, RefPtr<AsyncCallChain> > m_executionContextTa
     skCallChains; |   97     HashMap<ExecutionContextTask*, RefPtr<AsyncCallChain> > m_executionContextTa
     skCallChains; | 
|   86     HashMap<String, RefPtr<AsyncCallChain> > m_v8AsyncTaskCallChains; |   98     HashMap<String, RefPtr<AsyncCallChain> > m_v8AsyncTaskCallChains; | 
 |   99     HashMap<int, RefPtr<AsyncCallChain> > m_asyncOperationCallChains; | 
|   87 }; |  100 }; | 
|   88  |  101  | 
|   89 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget) |  102 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget) | 
|   90 { |  103 { | 
|   91     const AtomicString& interfaceName = eventTarget->interfaceName(); |  104     const AtomicString& interfaceName = eventTarget->interfaceName(); | 
|   92     if (interfaceName == EventTargetNames::XMLHttpRequest) |  105     if (interfaceName == EventTargetNames::XMLHttpRequest) | 
|   93         return static_cast<XMLHttpRequest*>(eventTarget); |  106         return static_cast<XMLHttpRequest*>(eventTarget); | 
|   94     if (interfaceName == EventTargetNames::XMLHttpRequestUpload) |  107     if (interfaceName == EventTargetNames::XMLHttpRequestUpload) | 
|   95         return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest()
     ; |  108         return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest()
     ; | 
|   96     return 0; |  109     return 0; | 
|   97 } |  110 } | 
|   98  |  111  | 
|   99 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description,
      const ScriptValue& callFrames) |  112 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description,
      const ScriptValue& callFrames) | 
|  100     : m_description(description) |  113     : m_description(description) | 
|  101     , m_callFrames(callFrames) |  114     , m_callFrames(callFrames) | 
|  102 { |  115 { | 
|  103 } |  116 } | 
|  104  |  117  | 
|  105 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() |  118 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() | 
|  106 { |  119 { | 
|  107 } |  120 } | 
|  108  |  121  | 
|  109 AsyncCallStackTracker::AsyncCallStackTracker() |  122 AsyncCallStackTracker::AsyncCallStackTracker() | 
|  110     : m_maxAsyncCallStackDepth(0) |  123     : m_maxAsyncCallStackDepth(0) | 
 |  124     , m_nestedAsyncCallCount(0) | 
|  111 { |  125 { | 
|  112 } |  126 } | 
|  113  |  127  | 
|  114 void AsyncCallStackTracker::setAsyncCallStackDepth(int depth) |  128 void AsyncCallStackTracker::setAsyncCallStackDepth(int depth) | 
|  115 { |  129 { | 
|  116     if (depth <= 0) { |  130     if (depth <= 0) { | 
|  117         m_maxAsyncCallStackDepth = 0; |  131         m_maxAsyncCallStackDepth = 0; | 
|  118         clear(); |  132         clear(); | 
|  119     } else { |  133     } else { | 
|  120         m_maxAsyncCallStackDepth = depth; |  134         m_maxAsyncCallStackDepth = depth; | 
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  351 void AsyncCallStackTracker::willHandleV8AsyncTask(ExecutionContext* context, con
     st String& eventName, int id) |  365 void AsyncCallStackTracker::willHandleV8AsyncTask(ExecutionContext* context, con
     st String& eventName, int id) | 
|  352 { |  366 { | 
|  353     ASSERT(context); |  367     ASSERT(context); | 
|  354     ASSERT(isEnabled()); |  368     ASSERT(isEnabled()); | 
|  355     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  369     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 
|  356         setCurrentAsyncCallChain(context, data->m_v8AsyncTaskCallChains.take(mak
     eV8AsyncTaskUniqueId(eventName, id))); |  370         setCurrentAsyncCallChain(context, data->m_v8AsyncTaskCallChains.take(mak
     eV8AsyncTaskUniqueId(eventName, id))); | 
|  357     else |  371     else | 
|  358         setCurrentAsyncCallChain(context, nullptr); |  372         setCurrentAsyncCallChain(context, nullptr); | 
|  359 } |  373 } | 
|  360  |  374  | 
 |  375 int AsyncCallStackTracker::traceAsyncOperationStarting(ExecutionContext* context
     , const String& operationName, const ScriptValue& callFrames) | 
 |  376 { | 
 |  377     ASSERT(context); | 
 |  378     ASSERT(isEnabled()); | 
 |  379     if (!validateCallFrames(callFrames)) | 
 |  380         return 0; | 
 |  381     ExecutionContextData* data = createContextDataIfNeeded(context); | 
 |  382     int id = data->circularSequentialID(); | 
 |  383     while (data->m_asyncOperationCallChains.contains(id)) | 
 |  384         id = data->circularSequentialID(); | 
 |  385     data->m_asyncOperationCallChains.set(id, createAsyncCallChain(operationName,
      callFrames)); | 
 |  386     return id; | 
 |  387 } | 
 |  388  | 
 |  389 void AsyncCallStackTracker::traceAsyncOperationCompleted(ExecutionContext* conte
     xt, int operationId) | 
 |  390 { | 
 |  391     ASSERT(context); | 
 |  392     ASSERT(isEnabled()); | 
 |  393     if (operationId <= 0) | 
 |  394         return; | 
 |  395     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 
 |  396         data->m_asyncOperationCallChains.remove(operationId); | 
 |  397 } | 
 |  398  | 
 |  399 void AsyncCallStackTracker::traceAsyncCallbackStarting(ExecutionContext* context
     , int operationId) | 
 |  400 { | 
 |  401     ASSERT(context); | 
 |  402     ASSERT(isEnabled()); | 
 |  403     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 
 |  404         setCurrentAsyncCallChain(context, operationId > 0 ? data->m_asyncOperati
     onCallChains.get(operationId) : nullptr); | 
 |  405     else | 
 |  406         setCurrentAsyncCallChain(context, nullptr); | 
 |  407 } | 
 |  408  | 
|  361 void AsyncCallStackTracker::didFireAsyncCall() |  409 void AsyncCallStackTracker::didFireAsyncCall() | 
|  362 { |  410 { | 
|  363     clearCurrentAsyncCallChain(); |  411     clearCurrentAsyncCallChain(); | 
|  364 } |  412 } | 
|  365  |  413  | 
|  366 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA
     syncCallChain(const String& description, const ScriptValue& callFrames) |  414 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA
     syncCallChain(const String& description, const ScriptValue& callFrames) | 
|  367 { |  415 { | 
|  368     if (callFrames.isEmpty()) { |  416     if (callFrames.isEmpty()) { | 
|  369         ASSERT(m_currentAsyncCallChain); |  417         ASSERT(m_currentAsyncCallChain); | 
|  370         return m_currentAsyncCallChain; // Propogate async call stack chain. |  418         return m_currentAsyncCallChain; // Propogate async call stack chain. | 
|  371     } |  419     } | 
|  372     RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC
     allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr
     acker::AsyncCallChain()); |  420     RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC
     allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr
     acker::AsyncCallChain()); | 
|  373     ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); |  421     ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); | 
|  374     chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta
     ck(description, callFrames))); |  422     chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta
     ck(description, callFrames))); | 
|  375     return chain.release(); |  423     return chain.release(); | 
|  376 } |  424 } | 
|  377  |  425  | 
|  378 void AsyncCallStackTracker::setCurrentAsyncCallChain(ExecutionContext* context, 
     PassRefPtr<AsyncCallChain> chain) |  426 void AsyncCallStackTracker::setCurrentAsyncCallChain(ExecutionContext* context, 
     PassRefPtr<AsyncCallChain> chain) | 
|  379 { |  427 { | 
|  380     if (V8RecursionScope::recursionLevel(toIsolate(context))) { |  428     if (chain && !V8RecursionScope::recursionLevel(toIsolate(context))) { | 
 |  429         // Current AsyncCallChain corresponds to the bottommost JS call frame. | 
 |  430         m_currentAsyncCallChain = chain; | 
 |  431         m_nestedAsyncCallCount = 1; | 
 |  432     } else { | 
|  381         if (m_currentAsyncCallChain) |  433         if (m_currentAsyncCallChain) | 
|  382             ++m_nestedAsyncCallCount; |  434             ++m_nestedAsyncCallCount; | 
|  383     } else { |  | 
|  384         // Current AsyncCallChain corresponds to the bottommost JS call frame. |  | 
|  385         m_currentAsyncCallChain = chain; |  | 
|  386         m_nestedAsyncCallCount = m_currentAsyncCallChain ? 1 : 0; |  | 
|  387     } |  435     } | 
|  388 } |  436 } | 
|  389  |  437  | 
|  390 void AsyncCallStackTracker::clearCurrentAsyncCallChain() |  438 void AsyncCallStackTracker::clearCurrentAsyncCallChain() | 
|  391 { |  439 { | 
|  392     if (!m_nestedAsyncCallCount) |  440     if (!m_nestedAsyncCallCount) | 
|  393         return; |  441         return; | 
|  394     --m_nestedAsyncCallCount; |  442     --m_nestedAsyncCallCount; | 
|  395     if (!m_nestedAsyncCallCount) |  443     if (!m_nestedAsyncCallCount) | 
|  396         m_currentAsyncCallChain.clear(); |  444         m_currentAsyncCallChain.clear(); | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
|  421 { |  469 { | 
|  422     m_currentAsyncCallChain.clear(); |  470     m_currentAsyncCallChain.clear(); | 
|  423     m_nestedAsyncCallCount = 0; |  471     m_nestedAsyncCallCount = 0; | 
|  424     ExecutionContextDataMap copy; |  472     ExecutionContextDataMap copy; | 
|  425     m_executionContextDataMap.swap(copy); |  473     m_executionContextDataMap.swap(copy); | 
|  426     for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e
     nd(); ++it) |  474     for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e
     nd(); ++it) | 
|  427         delete it->value; |  475         delete it->value; | 
|  428 } |  476 } | 
|  429  |  477  | 
|  430 } // namespace blink |  478 } // namespace blink | 
| OLD | NEW |