OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/inspector/v8-debugger.h" | 5 #include "src/inspector/v8-debugger.h" |
6 | 6 |
7 #include "src/inspector/debugger-script.h" | 7 #include "src/inspector/debugger-script.h" |
8 #include "src/inspector/inspected-context.h" | 8 #include "src/inspector/inspected-context.h" |
9 #include "src/inspector/protocol/Protocol.h" | 9 #include "src/inspector/protocol/Protocol.h" |
10 #include "src/inspector/script-breakpoint.h" | 10 #include "src/inspector/script-breakpoint.h" |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, | 556 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, |
557 const v8::debug::Location& start, | 557 const v8::debug::Location& start, |
558 const v8::debug::Location& end) { | 558 const v8::debug::Location& end) { |
559 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); | 559 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); |
560 if (!agent) return false; | 560 if (!agent) return false; |
561 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, | 561 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, |
562 end); | 562 end); |
563 } | 563 } |
564 | 564 |
565 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, | 565 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, |
566 int id) { | 566 int id, int parentId) { |
567 if (!m_maxAsyncCallStackDepth) return; | 567 if (!m_maxAsyncCallStackDepth) return; |
568 // Async task events from Promises are given misaligned pointers to prevent | 568 // Async task events from Promises are given misaligned pointers to prevent |
569 // from overlapping with other Blink task identifiers. There is a single | 569 // from overlapping with other Blink task identifiers. There is a single |
570 // namespace of such ids, managed by src/js/promise.js. | 570 // namespace of such ids, managed by src/js/promise.js. |
571 void* ptr = reinterpret_cast<void*>(id * 2 + 1); | 571 void* ptr = reinterpret_cast<void*>(id * 2 + 1); |
572 switch (type) { | 572 switch (type) { |
| 573 case v8::debug::kDebugPromiseCreated: |
| 574 asyncTaskCreated( |
| 575 ptr, parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr); |
| 576 break; |
573 case v8::debug::kDebugEnqueueAsyncFunction: | 577 case v8::debug::kDebugEnqueueAsyncFunction: |
574 asyncTaskScheduled("async function", ptr, true); | 578 asyncTaskScheduled("async function", ptr, true); |
575 break; | 579 break; |
576 case v8::debug::kDebugEnqueuePromiseResolve: | 580 case v8::debug::kDebugEnqueuePromiseResolve: |
577 asyncTaskScheduled("Promise.resolve", ptr, true); | 581 asyncTaskScheduled("Promise.resolve", ptr, true); |
578 break; | 582 break; |
579 case v8::debug::kDebugEnqueuePromiseReject: | 583 case v8::debug::kDebugEnqueuePromiseReject: |
580 asyncTaskScheduled("Promise.reject", ptr, true); | 584 asyncTaskScheduled("Promise.reject", ptr, true); |
581 break; | 585 break; |
582 case v8::debug::kDebugEnqueuePromiseResolveThenableJob: | |
583 asyncTaskScheduled("PromiseResolveThenableJob", ptr, true); | |
584 break; | |
585 case v8::debug::kDebugPromiseCollected: | 586 case v8::debug::kDebugPromiseCollected: |
586 asyncTaskCanceled(ptr); | 587 asyncTaskCanceled(ptr); |
587 break; | 588 break; |
588 case v8::debug::kDebugWillHandle: | 589 case v8::debug::kDebugWillHandle: |
589 asyncTaskStarted(ptr); | 590 asyncTaskStarted(ptr); |
590 break; | 591 break; |
591 case v8::debug::kDebugDidHandle: | 592 case v8::debug::kDebugDidHandle: |
592 asyncTaskFinished(ptr); | 593 asyncTaskFinished(ptr); |
593 break; | 594 break; |
594 } | 595 } |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 for (const auto& pair : m_maxAsyncCallStackDepthMap) { | 851 for (const auto& pair : m_maxAsyncCallStackDepthMap) { |
851 if (pair.second > maxAsyncCallStackDepth) | 852 if (pair.second > maxAsyncCallStackDepth) |
852 maxAsyncCallStackDepth = pair.second; | 853 maxAsyncCallStackDepth = pair.second; |
853 } | 854 } |
854 | 855 |
855 if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) return; | 856 if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) return; |
856 m_maxAsyncCallStackDepth = maxAsyncCallStackDepth; | 857 m_maxAsyncCallStackDepth = maxAsyncCallStackDepth; |
857 if (!maxAsyncCallStackDepth) allAsyncTasksCanceled(); | 858 if (!maxAsyncCallStackDepth) allAsyncTasksCanceled(); |
858 } | 859 } |
859 | 860 |
| 861 void V8Debugger::asyncTaskCreated(void* task, void* parentTask) { |
| 862 if (!m_maxAsyncCallStackDepth) return; |
| 863 if (parentTask) m_parentTask[task] = parentTask; |
| 864 } |
| 865 |
860 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, | 866 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
861 bool recurring) { | 867 bool recurring) { |
862 if (!m_maxAsyncCallStackDepth) return; | 868 if (!m_maxAsyncCallStackDepth) return; |
863 asyncTaskScheduled(toString16(taskName), task, recurring); | 869 asyncTaskScheduled(toString16(taskName), task, recurring); |
864 } | 870 } |
865 | 871 |
866 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, | 872 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, |
867 bool recurring) { | 873 bool recurring) { |
868 if (!m_maxAsyncCallStackDepth) return; | 874 if (!m_maxAsyncCallStackDepth) return; |
869 v8::HandleScope scope(m_isolate); | 875 v8::HandleScope scope(m_isolate); |
(...skipping 14 matching lines...) Expand all Loading... |
884 void* taskToRemove = m_idToTask.begin()->second; | 890 void* taskToRemove = m_idToTask.begin()->second; |
885 asyncTaskCanceled(taskToRemove); | 891 asyncTaskCanceled(taskToRemove); |
886 } | 892 } |
887 } | 893 } |
888 } | 894 } |
889 | 895 |
890 void V8Debugger::asyncTaskCanceled(void* task) { | 896 void V8Debugger::asyncTaskCanceled(void* task) { |
891 if (!m_maxAsyncCallStackDepth) return; | 897 if (!m_maxAsyncCallStackDepth) return; |
892 m_asyncTaskStacks.erase(task); | 898 m_asyncTaskStacks.erase(task); |
893 m_recurringTasks.erase(task); | 899 m_recurringTasks.erase(task); |
| 900 m_parentTask.erase(task); |
894 auto it = m_taskToId.find(task); | 901 auto it = m_taskToId.find(task); |
895 if (it == m_taskToId.end()) return; | 902 if (it == m_taskToId.end()) return; |
896 m_idToTask.erase(it->second); | 903 m_idToTask.erase(it->second); |
897 m_taskToId.erase(it); | 904 m_taskToId.erase(it); |
898 } | 905 } |
899 | 906 |
900 void V8Debugger::asyncTaskStarted(void* task) { | 907 void V8Debugger::asyncTaskStarted(void* task) { |
901 if (!m_maxAsyncCallStackDepth) return; | 908 if (!m_maxAsyncCallStackDepth) return; |
902 m_currentTasks.push_back(task); | 909 m_currentTasks.push_back(task); |
903 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(task); | 910 auto parentIt = m_parentTask.find(task); |
| 911 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( |
| 912 parentIt == m_parentTask.end() ? task : parentIt->second); |
904 // Needs to support following order of events: | 913 // Needs to support following order of events: |
905 // - asyncTaskScheduled | 914 // - asyncTaskScheduled |
906 // <-- attached here --> | 915 // <-- attached here --> |
907 // - asyncTaskStarted | 916 // - asyncTaskStarted |
908 // - asyncTaskCanceled <-- canceled before finished | 917 // - asyncTaskCanceled <-- canceled before finished |
909 // <-- async stack requested here --> | 918 // <-- async stack requested here --> |
910 // - asyncTaskFinished | 919 // - asyncTaskFinished |
911 std::unique_ptr<V8StackTraceImpl> stack; | 920 std::unique_ptr<V8StackTraceImpl> stack; |
912 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) | 921 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) |
913 stack = stackIt->second->cloneImpl(); | 922 stack = stackIt->second->cloneImpl(); |
914 m_currentStacks.push_back(std::move(stack)); | 923 m_currentStacks.push_back(std::move(stack)); |
915 } | 924 } |
916 | 925 |
917 void V8Debugger::asyncTaskFinished(void* task) { | 926 void V8Debugger::asyncTaskFinished(void* task) { |
918 if (!m_maxAsyncCallStackDepth) return; | 927 if (!m_maxAsyncCallStackDepth) return; |
919 // We could start instrumenting half way and the stack is empty. | 928 // We could start instrumenting half way and the stack is empty. |
920 if (!m_currentStacks.size()) return; | 929 if (!m_currentStacks.size()) return; |
921 | 930 |
922 DCHECK(m_currentTasks.back() == task); | 931 DCHECK(m_currentTasks.back() == task); |
923 m_currentTasks.pop_back(); | 932 m_currentTasks.pop_back(); |
924 | 933 |
925 m_currentStacks.pop_back(); | 934 m_currentStacks.pop_back(); |
926 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { | 935 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { |
927 m_asyncTaskStacks.erase(task); | 936 asyncTaskCanceled(task); |
928 auto it = m_taskToId.find(task); | |
929 if (it == m_taskToId.end()) return; | |
930 m_idToTask.erase(it->second); | |
931 m_taskToId.erase(it); | |
932 } | 937 } |
933 } | 938 } |
934 | 939 |
935 void V8Debugger::allAsyncTasksCanceled() { | 940 void V8Debugger::allAsyncTasksCanceled() { |
936 m_asyncTaskStacks.clear(); | 941 m_asyncTaskStacks.clear(); |
937 m_recurringTasks.clear(); | 942 m_recurringTasks.clear(); |
938 m_currentStacks.clear(); | 943 m_currentStacks.clear(); |
939 m_currentTasks.clear(); | 944 m_currentTasks.clear(); |
| 945 m_parentTask.clear(); |
940 m_idToTask.clear(); | 946 m_idToTask.clear(); |
941 m_taskToId.clear(); | 947 m_taskToId.clear(); |
942 m_lastTaskId = 0; | 948 m_lastTaskId = 0; |
943 } | 949 } |
944 | 950 |
945 void V8Debugger::muteScriptParsedEvents() { | 951 void V8Debugger::muteScriptParsedEvents() { |
946 ++m_ignoreScriptParsedEventsCounter; | 952 ++m_ignoreScriptParsedEventsCounter; |
947 } | 953 } |
948 | 954 |
949 void V8Debugger::unmuteScriptParsedEvents() { | 955 void V8Debugger::unmuteScriptParsedEvents() { |
(...skipping 12 matching lines...) Expand all Loading... |
962 | 968 |
963 size_t stackSize = | 969 size_t stackSize = |
964 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 970 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
965 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 971 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
966 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 972 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
967 | 973 |
968 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 974 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
969 } | 975 } |
970 | 976 |
971 } // namespace v8_inspector | 977 } // namespace v8_inspector |
OLD | NEW |