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

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

Issue 383123009: DevTools: Support async call stacks for FileSystem API (part 1). (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 months 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 22 matching lines...) Expand all
33 33
34 #include "bindings/core/v8/V8Binding.h" 34 #include "bindings/core/v8/V8Binding.h"
35 #include "bindings/core/v8/V8RecursionScope.h" 35 #include "bindings/core/v8/V8RecursionScope.h"
36 #include "core/dom/ContextLifecycleObserver.h" 36 #include "core/dom/ContextLifecycleObserver.h"
37 #include "core/dom/ExecutionContext.h" 37 #include "core/dom/ExecutionContext.h"
38 #include "core/dom/ExecutionContextTask.h" 38 #include "core/dom/ExecutionContextTask.h"
39 #include "core/events/Event.h" 39 #include "core/events/Event.h"
40 #include "core/events/EventTarget.h" 40 #include "core/events/EventTarget.h"
41 #include "core/xml/XMLHttpRequest.h" 41 #include "core/xml/XMLHttpRequest.h"
42 #include "core/xml/XMLHttpRequestUpload.h" 42 #include "core/xml/XMLHttpRequestUpload.h"
43 #include "platform/AsyncFileSystemCallbacks.h"
43 #include "wtf/text/StringBuilder.h" 44 #include "wtf/text/StringBuilder.h"
44 #include "wtf/text/StringHash.h" 45 #include "wtf/text/StringHash.h"
45 #include <v8.h> 46 #include <v8.h>
46 47
47 namespace { 48 namespace {
48 49
49 static const char setTimeoutName[] = "setTimeout"; 50 static const char setTimeoutName[] = "setTimeout";
50 static const char setIntervalName[] = "setInterval"; 51 static const char setIntervalName[] = "setInterval";
51 static const char requestAnimationFrameName[] = "requestAnimationFrame"; 52 static const char requestAnimationFrameName[] = "requestAnimationFrame";
52 static const char xhrSendName[] = "XMLHttpRequest.send"; 53 static const char xhrSendName[] = "XMLHttpRequest.send";
53 static const char enqueueMutationRecordName[] = "Mutation"; 54 static const char enqueueMutationRecordName[] = "Mutation";
55 static const char fileSystemName[] = "FileSystem";
54 56
55 } 57 }
56 58
57 namespace WebCore { 59 namespace WebCore {
58 60
59 class AsyncCallStackTracker::ExecutionContextData FINAL : public ContextLifecycl eObserver { 61 class AsyncCallStackTracker::ExecutionContextData FINAL : public ContextLifecycl eObserver {
60 WTF_MAKE_FAST_ALLOCATED; 62 WTF_MAKE_FAST_ALLOCATED;
61 public: 63 public:
62 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu tionContext) 64 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu tionContext)
63 : ContextLifecycleObserver(executionContext) 65 : ContextLifecycleObserver(executionContext)
(...skipping 12 matching lines...) Expand all
76 78
77 public: 79 public:
78 AsyncCallStackTracker* m_tracker; 80 AsyncCallStackTracker* m_tracker;
79 HashSet<int> m_intervalTimerIds; 81 HashSet<int> m_intervalTimerIds;
80 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains; 82 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains;
81 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains; 83 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains;
82 HashMap<Event*, RefPtr<AsyncCallChain> > m_eventCallChains; 84 HashMap<Event*, RefPtr<AsyncCallChain> > m_eventCallChains;
83 HashMap<EventTarget*, RefPtr<AsyncCallChain> > m_xhrCallChains; 85 HashMap<EventTarget*, RefPtr<AsyncCallChain> > m_xhrCallChains;
84 HashMap<MutationObserver*, RefPtr<AsyncCallChain> > m_mutationObserverCallCh ains; 86 HashMap<MutationObserver*, RefPtr<AsyncCallChain> > m_mutationObserverCallCh ains;
85 HashMap<ExecutionContextTask*, RefPtr<AsyncCallChain> > m_executionContextTa skCallChains; 87 HashMap<ExecutionContextTask*, RefPtr<AsyncCallChain> > m_executionContextTa skCallChains;
88 HashMap<AsyncFileSystemCallbacks*, RefPtr<AsyncCallChain> > m_fileSystemCall Chains;
86 HashMap<String, RefPtr<AsyncCallChain> > m_v8AsyncTaskCallChains; 89 HashMap<String, RefPtr<AsyncCallChain> > m_v8AsyncTaskCallChains;
87 }; 90 };
88 91
89 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget) 92 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget)
90 { 93 {
91 const AtomicString& interfaceName = eventTarget->interfaceName(); 94 const AtomicString& interfaceName = eventTarget->interfaceName();
92 if (interfaceName == EventTargetNames::XMLHttpRequest) 95 if (interfaceName == EventTargetNames::XMLHttpRequest)
93 return static_cast<XMLHttpRequest*>(eventTarget); 96 return static_cast<XMLHttpRequest*>(eventTarget);
94 if (interfaceName == EventTargetNames::XMLHttpRequestUpload) 97 if (interfaceName == EventTargetNames::XMLHttpRequestUpload)
95 return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest() ; 98 return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest() ;
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 void AsyncCallStackTracker::willPerformExecutionContextTask(ExecutionContext* co ntext, ExecutionContextTask* task) 323 void AsyncCallStackTracker::willPerformExecutionContextTask(ExecutionContext* co ntext, ExecutionContextTask* task)
321 { 324 {
322 ASSERT(context); 325 ASSERT(context);
323 ASSERT(isEnabled()); 326 ASSERT(isEnabled());
324 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) 327 if (ExecutionContextData* data = m_executionContextDataMap.get(context))
325 setCurrentAsyncCallChain(context, data->m_executionContextTaskCallChains .take(task)); 328 setCurrentAsyncCallChain(context, data->m_executionContextTaskCallChains .take(task));
326 else 329 else
327 setCurrentAsyncCallChain(context, nullptr); 330 setCurrentAsyncCallChain(context, nullptr);
328 } 331 }
329 332
333 void AsyncCallStackTracker::didEnqueueAsyncFileSystemCallback(ExecutionContext* context, AsyncFileSystemCallbacks* callback, const ScriptValue& callFrames)
334 {
335 ASSERT(context);
336 ASSERT(isEnabled());
337 if (!validateCallFrames(callFrames))
338 return;
339 ExecutionContextData* data = createContextDataIfNeeded(context);
340 data->m_fileSystemCallChains.set(callback, createAsyncCallChain(fileSystemNa me, callFrames));
341 }
342
343 void AsyncCallStackTracker::didRemoveAsyncFileSystemCallback(ExecutionContext* c ontext, AsyncFileSystemCallbacks* callback)
344 {
345 ASSERT(context);
346 ASSERT(isEnabled());
347 if (ExecutionContextData* data = m_executionContextDataMap.get(context))
348 data->m_fileSystemCallChains.remove(callback);
349 }
350
351 void AsyncCallStackTracker::willHandleAsyncFileSystemCallback(ExecutionContext* context, AsyncFileSystemCallbacks* callback, bool hasMore)
352 {
353 ASSERT(context);
354 ASSERT(isEnabled());
355 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) {
356 if (hasMore)
357 setCurrentAsyncCallChain(context, data->m_fileSystemCallChains.get(c allback));
yurys 2014/07/14 14:55:54 style: consider extracting setCurrentAsyncCallChai
358 else
359 setCurrentAsyncCallChain(context, data->m_fileSystemCallChains.take( callback));
360 } else {
361 setCurrentAsyncCallChain(context, nullptr);
362 }
363 }
364
330 static String makeV8AsyncTaskUniqueId(const String& eventName, int id) 365 static String makeV8AsyncTaskUniqueId(const String& eventName, int id)
331 { 366 {
332 StringBuilder builder; 367 StringBuilder builder;
333 builder.append(eventName); 368 builder.append(eventName);
334 builder.appendNumber(id); 369 builder.appendNumber(id);
335 return builder.toString(); 370 return builder.toString();
336 } 371 }
337 372
338 void AsyncCallStackTracker::didEnqueueV8AsyncTask(ExecutionContext* context, con st String& eventName, int id, const ScriptValue& callFrames) 373 void AsyncCallStackTracker::didEnqueueV8AsyncTask(ExecutionContext* context, con st String& eventName, int id, const ScriptValue& callFrames)
339 { 374 {
(...skipping 13 matching lines...) Expand all
353 setCurrentAsyncCallChain(context, data->m_v8AsyncTaskCallChains.take(mak eV8AsyncTaskUniqueId(eventName, id))); 388 setCurrentAsyncCallChain(context, data->m_v8AsyncTaskCallChains.take(mak eV8AsyncTaskUniqueId(eventName, id)));
354 else 389 else
355 setCurrentAsyncCallChain(context, nullptr); 390 setCurrentAsyncCallChain(context, nullptr);
356 } 391 }
357 392
358 void AsyncCallStackTracker::didFireAsyncCall() 393 void AsyncCallStackTracker::didFireAsyncCall()
359 { 394 {
360 clearCurrentAsyncCallChain(); 395 clearCurrentAsyncCallChain();
361 } 396 }
362 397
398 void AsyncCallStackTracker::willRescheduleAsyncCallChain()
399 {
400 ASSERT(isEnabled());
401 if (!m_rescheduledAsyncCallChain)
402 m_rescheduleNextAsyncCallChain = true;
403 }
404
405 void AsyncCallStackTracker::didRescheduleAsyncCallChain()
406 {
407 ASSERT(isEnabled());
408 m_rescheduleNextAsyncCallChain = false;
409 m_rescheduledAsyncCallChain.clear();
410 }
411
363 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const String& description, const ScriptValue& callFrames) 412 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const String& description, const ScriptValue& callFrames)
364 { 413 {
414 // Check if we should propogate the async call stack chain.
415 if (m_rescheduledAsyncCallChain)
416 return m_rescheduledAsyncCallChain;
365 if (callFrames.isEmpty()) { 417 if (callFrames.isEmpty()) {
366 ASSERT(m_currentAsyncCallChain); 418 ASSERT(m_currentAsyncCallChain);
367 return m_currentAsyncCallChain; // Propogate async call stack chain. 419 return m_currentAsyncCallChain;
368 } 420 }
369 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain()); 421 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain());
370 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); 422 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1);
371 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta ck(description, callFrames))); 423 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta ck(description, callFrames)));
372 return chain.release(); 424 return chain.release();
373 } 425 }
374 426
375 void AsyncCallStackTracker::setCurrentAsyncCallChain(ExecutionContext* context, PassRefPtr<AsyncCallChain> chain) 427 void AsyncCallStackTracker::setCurrentAsyncCallChain(ExecutionContext* context, PassRefPtr<AsyncCallChain> chain)
376 { 428 {
429 if (m_rescheduleNextAsyncCallChain) {
430 m_rescheduleNextAsyncCallChain = false;
431 m_rescheduledAsyncCallChain = chain.get();
432 }
377 if (V8RecursionScope::recursionLevel(toIsolate(context))) { 433 if (V8RecursionScope::recursionLevel(toIsolate(context))) {
378 if (m_currentAsyncCallChain) 434 if (m_currentAsyncCallChain)
379 ++m_nestedAsyncCallCount; 435 ++m_nestedAsyncCallCount;
380 } else { 436 } else {
381 // Current AsyncCallChain corresponds to the bottommost JS call frame. 437 // Current AsyncCallChain corresponds to the bottommost JS call frame.
382 m_currentAsyncCallChain = chain; 438 m_currentAsyncCallChain = chain;
383 m_nestedAsyncCallCount = m_currentAsyncCallChain ? 1 : 0; 439 m_nestedAsyncCallCount = m_currentAsyncCallChain ? 1 : 0;
384 } 440 }
385 } 441 }
386 442
387 void AsyncCallStackTracker::clearCurrentAsyncCallChain() 443 void AsyncCallStackTracker::clearCurrentAsyncCallChain()
388 { 444 {
389 if (!m_nestedAsyncCallCount) 445 if (!m_nestedAsyncCallCount)
390 return; 446 return;
391 --m_nestedAsyncCallCount; 447 --m_nestedAsyncCallCount;
392 if (!m_nestedAsyncCallCount) 448 if (!m_nestedAsyncCallCount)
393 m_currentAsyncCallChain.clear(); 449 m_currentAsyncCallChain.clear();
394 } 450 }
395 451
396 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain, unsigned maxDepth) 452 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain, unsigned maxDepth)
397 { 453 {
398 while (chain->m_callStacks.size() > maxDepth) 454 while (chain->m_callStacks.size() > maxDepth)
399 chain->m_callStacks.removeLast(); 455 chain->m_callStacks.removeLast();
400 } 456 }
401 457
402 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) 458 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames)
403 { 459 {
404 return !callFrames.isEmpty() || m_currentAsyncCallChain; 460 return !callFrames.isEmpty() || m_currentAsyncCallChain || m_rescheduledAsyn cCallChain;
405 } 461 }
406 462
407 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex tDataIfNeeded(ExecutionContext* context) 463 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex tDataIfNeeded(ExecutionContext* context)
408 { 464 {
409 ExecutionContextData* data = m_executionContextDataMap.get(context); 465 ExecutionContextData* data = m_executionContextDataMap.get(context);
410 if (!data) { 466 if (!data) {
411 data = new AsyncCallStackTracker::ExecutionContextData(this, context); 467 data = new AsyncCallStackTracker::ExecutionContextData(this, context);
412 m_executionContextDataMap.set(context, data); 468 m_executionContextDataMap.set(context, data);
413 } 469 }
414 return data; 470 return data;
415 } 471 }
416 472
417 void AsyncCallStackTracker::clear() 473 void AsyncCallStackTracker::clear()
418 { 474 {
419 m_currentAsyncCallChain.clear(); 475 m_currentAsyncCallChain.clear();
420 m_nestedAsyncCallCount = 0; 476 m_nestedAsyncCallCount = 0;
477 m_rescheduleNextAsyncCallChain = false;
478 m_rescheduledAsyncCallChain.clear();
421 ExecutionContextDataMap copy; 479 ExecutionContextDataMap copy;
422 m_executionContextDataMap.swap(copy); 480 m_executionContextDataMap.swap(copy);
423 for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e nd(); ++it) 481 for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e nd(); ++it)
424 delete it->value; 482 delete it->value;
425 } 483 }
426 484
427 } // namespace WebCore 485 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698