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" |
11 #include "src/inspector/string-util.h" | 11 #include "src/inspector/string-util.h" |
12 #include "src/inspector/v8-debugger-agent-impl.h" | 12 #include "src/inspector/v8-debugger-agent-impl.h" |
13 #include "src/inspector/v8-inspector-impl.h" | 13 #include "src/inspector/v8-inspector-impl.h" |
14 #include "src/inspector/v8-internal-value-type.h" | 14 #include "src/inspector/v8-internal-value-type.h" |
15 #include "src/inspector/v8-stack-trace-impl.h" | 15 #include "src/inspector/v8-stack-trace-impl.h" |
16 #include "src/inspector/v8-value-copier.h" | 16 #include "src/inspector/v8-value-copier.h" |
17 | 17 |
18 #include "include/v8-util.h" | 18 #include "include/v8-util.h" |
19 | 19 |
20 namespace v8_inspector { | 20 namespace v8_inspector { |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 // Based on DevTools frontend measurement, with asyncCallStackDepth = 4, | 24 static const int kMaxAsyncTaskStacks = 1024 * 1024; |
25 // average async call stack tail requires ~1 Kb. Let's reserve ~ 128 Mb | |
26 // for async stacks. | |
27 static const int kMaxAsyncTaskStacks = 128 * 1024; | |
28 | 25 |
29 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { | 26 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { |
30 return value ? v8::True(isolate) : v8::False(isolate); | 27 return value ? v8::True(isolate) : v8::False(isolate); |
31 } | 28 } |
32 | 29 |
33 V8DebuggerAgentImpl* agentForScript(V8InspectorImpl* inspector, | 30 V8DebuggerAgentImpl* agentForScript(V8InspectorImpl* inspector, |
34 v8::Local<v8::debug::Script> script) { | 31 v8::Local<v8::debug::Script> script) { |
35 v8::Local<v8::Value> contextData; | 32 v8::Local<v8::Value> contextData; |
36 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) { | 33 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) { |
37 return nullptr; | 34 return nullptr; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 } | 157 } |
161 | 158 |
162 V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) | 159 V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) |
163 : m_isolate(isolate), | 160 : m_isolate(isolate), |
164 m_inspector(inspector), | 161 m_inspector(inspector), |
165 m_enableCount(0), | 162 m_enableCount(0), |
166 m_breakpointsActivated(true), | 163 m_breakpointsActivated(true), |
167 m_runningNestedMessageLoop(false), | 164 m_runningNestedMessageLoop(false), |
168 m_ignoreScriptParsedEventsCounter(0), | 165 m_ignoreScriptParsedEventsCounter(0), |
169 m_maxAsyncCallStacks(kMaxAsyncTaskStacks), | 166 m_maxAsyncCallStacks(kMaxAsyncTaskStacks), |
170 m_lastTaskId(0), | |
171 m_maxAsyncCallStackDepth(0), | 167 m_maxAsyncCallStackDepth(0), |
172 m_pauseOnExceptionsState(v8::debug::NoBreakOnException), | 168 m_pauseOnExceptionsState(v8::debug::NoBreakOnException), |
173 m_wasmTranslation(isolate) {} | 169 m_wasmTranslation(isolate) {} |
174 | 170 |
175 V8Debugger::~V8Debugger() {} | 171 V8Debugger::~V8Debugger() {} |
176 | 172 |
177 void V8Debugger::enable() { | 173 void V8Debugger::enable() { |
178 if (m_enableCount++) return; | 174 if (m_enableCount++) return; |
179 DCHECK(!enabled()); | 175 DCHECK(!enabled()); |
180 v8::HandleScope scope(m_isolate); | 176 v8::HandleScope scope(m_isolate); |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 | 638 |
643 void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context, | 639 void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context, |
644 v8::debug::PromiseDebugActionType type, | 640 v8::debug::PromiseDebugActionType type, |
645 int id, int parentId, | 641 int id, int parentId, |
646 bool createdByUser) { | 642 bool createdByUser) { |
647 // Async task events from Promises are given misaligned pointers to prevent | 643 // Async task events from Promises are given misaligned pointers to prevent |
648 // from overlapping with other Blink task identifiers. | 644 // from overlapping with other Blink task identifiers. |
649 void* task = reinterpret_cast<void*>(id * 2 + 1); | 645 void* task = reinterpret_cast<void*>(id * 2 + 1); |
650 void* parentTask = | 646 void* parentTask = |
651 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; | 647 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; |
648 if (type == v8::debug::kDebugPromiseCollected) { | |
649 asyncTaskCanceledForStack(task); | |
650 asyncTaskCanceledForStepping(task); | |
651 return; | |
652 } | |
653 v8::Context::Scope contextScope(context); | |
dgozman
2017/04/17 17:49:08
Why new scope?
kozy
2017/04/17 21:34:17
It wasn't new - moved from v8::debug::kDebugPromis
| |
652 switch (type) { | 654 switch (type) { |
653 case v8::debug::kDebugPromiseCreated: | 655 case v8::debug::kDebugPromiseCreated: |
654 asyncTaskCreatedForStack(task, parentTask); | 656 asyncTaskCreatedForStack(task, parentTask); |
655 if (createdByUser && parentTask) { | 657 if (createdByUser && parentTask) asyncTaskCandidateForStepping(task); |
656 v8::Context::Scope contextScope(context); | |
657 asyncTaskCandidateForStepping(task); | |
658 } | |
659 break; | 658 break; |
660 case v8::debug::kDebugEnqueueAsyncFunction: | 659 case v8::debug::kDebugEnqueueAsyncFunction: |
661 asyncTaskScheduledForStack("async function", task, true); | 660 asyncTaskScheduledForStack("async function", task, true); |
662 break; | 661 break; |
663 case v8::debug::kDebugEnqueuePromiseResolve: | 662 case v8::debug::kDebugEnqueuePromiseResolve: |
664 asyncTaskScheduledForStack("Promise.resolve", task, true); | 663 asyncTaskScheduledForStack("Promise.resolve", task, true); |
665 break; | 664 break; |
666 case v8::debug::kDebugEnqueuePromiseReject: | 665 case v8::debug::kDebugEnqueuePromiseReject: |
667 asyncTaskScheduledForStack("Promise.reject", task, true); | 666 asyncTaskScheduledForStack("Promise.reject", task, true); |
668 break; | 667 break; |
669 case v8::debug::kDebugPromiseCollected: | |
670 asyncTaskCanceledForStack(task); | |
671 asyncTaskCanceledForStepping(task); | |
672 break; | |
673 case v8::debug::kDebugWillHandle: | 668 case v8::debug::kDebugWillHandle: |
674 asyncTaskStartedForStack(task); | 669 asyncTaskStartedForStack(task); |
675 asyncTaskStartedForStepping(task); | 670 asyncTaskStartedForStepping(task); |
676 break; | 671 break; |
677 case v8::debug::kDebugDidHandle: | 672 case v8::debug::kDebugDidHandle: |
678 asyncTaskFinishedForStack(task); | 673 asyncTaskFinishedForStack(task); |
679 asyncTaskFinishedForStepping(task); | 674 asyncTaskFinishedForStepping(task); |
680 break; | 675 break; |
676 case v8::debug::kDebugPromiseCollected: | |
677 UNREACHABLE(); | |
678 break; | |
681 } | 679 } |
682 } | 680 } |
683 | 681 |
684 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { | 682 std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncParent() { |
685 if (!m_currentStacks.size()) return nullptr; | 683 return m_currentAsyncParent.empty() ? nullptr : m_currentAsyncParent.back(); |
686 return m_currentStacks.back().get(); | |
687 } | 684 } |
688 | 685 |
689 V8StackTraceImpl* V8Debugger::currentAsyncTaskCreationStack() { | 686 std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncCreation() { |
690 if (!m_currentCreationStacks.size()) return nullptr; | 687 return m_currentAsyncCreation.empty() ? nullptr |
691 return m_currentCreationStacks.back().get(); | 688 : m_currentAsyncCreation.back(); |
692 } | 689 } |
693 | 690 |
694 void V8Debugger::compileDebuggerScript() { | 691 void V8Debugger::compileDebuggerScript() { |
695 if (!m_debuggerScript.IsEmpty()) { | 692 if (!m_debuggerScript.IsEmpty()) { |
696 UNREACHABLE(); | 693 UNREACHABLE(); |
697 return; | 694 return; |
698 } | 695 } |
699 | 696 |
700 v8::HandleScope scope(m_isolate); | 697 v8::HandleScope scope(m_isolate); |
701 v8::Context::Scope contextScope(debuggerContext()); | 698 v8::Context::Scope contextScope(debuggerContext()); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
822 functionScopes(context, function).ToLocal(&scopes)) { | 819 functionScopes(context, function).ToLocal(&scopes)) { |
823 createDataProperty(context, properties, properties->Length(), | 820 createDataProperty(context, properties, properties->Length(), |
824 toV8StringInternalized(m_isolate, "[[Scopes]]")); | 821 toV8StringInternalized(m_isolate, "[[Scopes]]")); |
825 createDataProperty(context, properties, properties->Length(), scopes); | 822 createDataProperty(context, properties, properties->Length(), scopes); |
826 } | 823 } |
827 } | 824 } |
828 return properties; | 825 return properties; |
829 } | 826 } |
830 | 827 |
831 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( | 828 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( |
832 v8::Local<v8::StackTrace> stackTrace) { | 829 v8::Local<v8::StackTrace> v8StackTrace) { |
833 return V8StackTraceImpl::create(this, currentContextGroupId(), stackTrace, | 830 return V8StackTraceImpl::create(this, currentContextGroupId(), v8StackTrace, |
834 V8StackTraceImpl::maxCallStackSizeToCapture); | 831 V8StackTraceImpl::maxCallStackSizeToCapture); |
835 } | 832 } |
836 | 833 |
837 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { | 834 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { |
838 if (depth <= 0) | 835 if (depth <= 0) |
839 m_maxAsyncCallStackDepthMap.erase(agent); | 836 m_maxAsyncCallStackDepthMap.erase(agent); |
840 else | 837 else |
841 m_maxAsyncCallStackDepthMap[agent] = depth; | 838 m_maxAsyncCallStackDepthMap[agent] = depth; |
842 | 839 |
843 int maxAsyncCallStackDepth = 0; | 840 int maxAsyncCallStackDepth = 0; |
844 for (const auto& pair : m_maxAsyncCallStackDepthMap) { | 841 for (const auto& pair : m_maxAsyncCallStackDepthMap) { |
845 if (pair.second > maxAsyncCallStackDepth) | 842 if (pair.second > maxAsyncCallStackDepth) |
846 maxAsyncCallStackDepth = pair.second; | 843 maxAsyncCallStackDepth = pair.second; |
847 } | 844 } |
848 | 845 |
849 if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) return; | 846 if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) return; |
850 m_maxAsyncCallStackDepth = maxAsyncCallStackDepth; | 847 m_maxAsyncCallStackDepth = maxAsyncCallStackDepth; |
851 if (!maxAsyncCallStackDepth) allAsyncTasksCanceled(); | 848 if (!maxAsyncCallStackDepth) allAsyncTasksCanceled(); |
852 } | 849 } |
853 | 850 |
854 void V8Debugger::registerAsyncTaskIfNeeded(void* task) { | |
855 if (m_taskToId.find(task) != m_taskToId.end()) return; | |
856 | |
857 int id = ++m_lastTaskId; | |
858 m_taskToId[task] = id; | |
859 m_idToTask[id] = task; | |
860 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) { | |
861 void* taskToRemove = m_idToTask.begin()->second; | |
862 asyncTaskCanceledForStack(taskToRemove); | |
863 } | |
864 } | |
865 | |
866 void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) { | 851 void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) { |
867 if (!m_maxAsyncCallStackDepth) return; | 852 if (!m_maxAsyncCallStackDepth) return; |
868 if (parentTask) m_parentTask[task] = parentTask; | 853 if (parentTask) m_parentTask[task] = parentTask; |
869 v8::HandleScope scope(m_isolate); | 854 v8::HandleScope scope(m_isolate); |
870 // We don't need to pass context group id here because we get this callback | 855 std::shared_ptr<AsyncStackTrace> asyncCreation = |
871 // from V8 for promise events only. | 856 AsyncStackTrace::capture(this, currentContextGroupId(), String16(), 1); |
872 // Passing one as maxStackSize forces no async chain for the new stack and | 857 if (asyncCreation && !asyncCreation->isEmpty()) { |
dgozman
2017/04/17 17:49:08
Leave this comment about passing one.
kozy
2017/04/17 21:34:17
But it's not a true - we don't grow exponentially,
| |
873 // allows us to not grow exponentially. | 858 m_asyncTaskCreationStacks[task] = asyncCreation; |
874 std::unique_ptr<V8StackTraceImpl> creationStack = | 859 m_allAsyncStacks.push_back(asyncCreation); |
875 V8StackTraceImpl::capture(this, 0, 1, String16()); | 860 ++m_asyncStacksCount; |
876 if (creationStack && !creationStack->isEmpty()) { | 861 collectOldAsyncStacksIfNeeded(); |
877 m_asyncTaskCreationStacks[task] = std::move(creationStack); | |
878 registerAsyncTaskIfNeeded(task); | |
879 } | 862 } |
880 } | 863 } |
881 | 864 |
882 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, | 865 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
883 bool recurring) { | 866 bool recurring) { |
884 asyncTaskScheduledForStack(toString16(taskName), task, recurring); | 867 asyncTaskScheduledForStack(toString16(taskName), task, recurring); |
885 asyncTaskCandidateForStepping(task); | 868 asyncTaskCandidateForStepping(task); |
886 } | 869 } |
887 | 870 |
888 void V8Debugger::asyncTaskCanceled(void* task) { | 871 void V8Debugger::asyncTaskCanceled(void* task) { |
889 asyncTaskCanceledForStack(task); | 872 asyncTaskCanceledForStack(task); |
890 asyncTaskCanceledForStepping(task); | 873 asyncTaskCanceledForStepping(task); |
891 } | 874 } |
892 | 875 |
893 void V8Debugger::asyncTaskStarted(void* task) { | 876 void V8Debugger::asyncTaskStarted(void* task) { |
894 asyncTaskStartedForStack(task); | 877 asyncTaskStartedForStack(task); |
895 asyncTaskStartedForStepping(task); | 878 asyncTaskStartedForStepping(task); |
896 } | 879 } |
897 | 880 |
898 void V8Debugger::asyncTaskFinished(void* task) { | 881 void V8Debugger::asyncTaskFinished(void* task) { |
899 asyncTaskFinishedForStack(task); | 882 asyncTaskFinishedForStack(task); |
900 asyncTaskFinishedForStepping(task); | 883 asyncTaskFinishedForStepping(task); |
901 } | 884 } |
902 | 885 |
903 void V8Debugger::asyncTaskScheduledForStack(const String16& taskName, | 886 void V8Debugger::asyncTaskScheduledForStack(const String16& taskName, |
904 void* task, bool recurring) { | 887 void* task, bool recurring) { |
905 if (!m_maxAsyncCallStackDepth) return; | 888 if (!m_maxAsyncCallStackDepth) return; |
906 v8::HandleScope scope(m_isolate); | 889 v8::HandleScope scope(m_isolate); |
907 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( | 890 std::shared_ptr<AsyncStackTrace> chain = |
dgozman
2017/04/17 17:49:08
nit: chain -> asyncStack
kozy
2017/04/17 21:34:17
Done.
| |
908 this, currentContextGroupId(), | 891 AsyncStackTrace::capture(this, currentContextGroupId(), taskName, |
909 V8StackTraceImpl::maxCallStackSizeToCapture, taskName); | 892 V8StackTraceImpl::maxCallStackSizeToCapture); |
910 if (chain) { | 893 if (chain) { |
911 m_asyncTaskStacks[task] = std::move(chain); | 894 m_asyncTaskStacks[task] = chain; |
912 if (recurring) m_recurringTasks.insert(task); | 895 if (recurring) m_recurringTasks.insert(task); |
913 registerAsyncTaskIfNeeded(task); | 896 |
897 m_allAsyncStacks.push_back(chain); | |
898 ++m_asyncStacksCount; | |
899 collectOldAsyncStacksIfNeeded(); | |
914 } | 900 } |
915 } | 901 } |
916 | 902 |
917 void V8Debugger::asyncTaskCanceledForStack(void* task) { | 903 void V8Debugger::asyncTaskCanceledForStack(void* task) { |
918 if (!m_maxAsyncCallStackDepth) return; | 904 if (!m_maxAsyncCallStackDepth) return; |
919 m_asyncTaskStacks.erase(task); | 905 m_asyncTaskStacks.erase(task); |
920 m_recurringTasks.erase(task); | 906 m_recurringTasks.erase(task); |
921 m_parentTask.erase(task); | 907 m_parentTask.erase(task); |
922 m_asyncTaskCreationStacks.erase(task); | 908 m_asyncTaskCreationStacks.erase(task); |
923 auto it = m_taskToId.find(task); | |
924 if (it == m_taskToId.end()) return; | |
925 m_idToTask.erase(it->second); | |
926 m_taskToId.erase(it); | |
927 } | 909 } |
928 | 910 |
929 void V8Debugger::asyncTaskStartedForStack(void* task) { | 911 void V8Debugger::asyncTaskStartedForStack(void* task) { |
930 if (!m_maxAsyncCallStackDepth) return; | 912 if (!m_maxAsyncCallStackDepth) return; |
931 m_currentTasks.push_back(task); | 913 m_currentTasks.push_back(task); |
932 auto parentIt = m_parentTask.find(task); | 914 auto parentIt = m_parentTask.find(task); |
933 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( | 915 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( |
934 parentIt == m_parentTask.end() ? task : parentIt->second); | 916 parentIt == m_parentTask.end() ? task : parentIt->second); |
935 // Needs to support following order of events: | 917 // Needs to support following order of events: |
936 // - asyncTaskScheduled | 918 // - asyncTaskScheduled |
937 // <-- attached here --> | 919 // <-- attached here --> |
938 // - asyncTaskStarted | 920 // - asyncTaskStarted |
939 // - asyncTaskCanceled <-- canceled before finished | 921 // - asyncTaskCanceled <-- canceled before finished |
940 // <-- async stack requested here --> | 922 // <-- async stack requested here --> |
941 // - asyncTaskFinished | 923 // - asyncTaskFinished |
942 std::unique_ptr<V8StackTraceImpl> stack; | 924 std::shared_ptr<AsyncStackTrace> asyncParent; |
943 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) | 925 if (stackIt != m_asyncTaskStacks.end()) asyncParent = stackIt->second.lock(); |
944 stack = stackIt->second->cloneImpl(); | |
945 auto itCreation = m_asyncTaskCreationStacks.find(task); | 926 auto itCreation = m_asyncTaskCreationStacks.find(task); |
946 if (stack && itCreation != m_asyncTaskCreationStacks.end()) { | 927 if (asyncParent && itCreation != m_asyncTaskCreationStacks.end()) { |
947 m_currentCreationStacks.push_back(itCreation->second->cloneImpl()); | 928 m_currentAsyncCreation.push_back(itCreation->second.lock()); |
948 } else { | 929 } else { |
949 m_currentCreationStacks.push_back(nullptr); | 930 m_currentAsyncCreation.push_back(nullptr); |
950 } | 931 } |
951 m_currentStacks.push_back(std::move(stack)); | 932 m_currentAsyncParent.push_back(asyncParent); |
952 } | 933 } |
953 | 934 |
954 void V8Debugger::asyncTaskFinishedForStack(void* task) { | 935 void V8Debugger::asyncTaskFinishedForStack(void* task) { |
955 if (!m_maxAsyncCallStackDepth) return; | 936 if (!m_maxAsyncCallStackDepth) return; |
956 // We could start instrumenting half way and the stack is empty. | 937 // We could start instrumenting half way and the stack is empty. |
957 if (!m_currentStacks.size()) return; | 938 if (!m_currentTasks.size()) return; |
958 DCHECK(m_currentTasks.back() == task); | 939 DCHECK(m_currentTasks.back() == task); |
959 m_currentTasks.pop_back(); | 940 m_currentTasks.pop_back(); |
960 | 941 |
961 DCHECK(m_currentStacks.size() == m_currentCreationStacks.size()); | 942 DCHECK(m_currentAsyncParent.size() == m_currentAsyncCreation.size()); |
962 m_currentStacks.pop_back(); | 943 m_currentAsyncParent.pop_back(); |
963 m_currentCreationStacks.pop_back(); | 944 m_currentAsyncCreation.pop_back(); |
945 | |
964 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { | 946 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { |
965 asyncTaskCanceledForStack(task); | 947 asyncTaskCanceledForStack(task); |
966 } | 948 } |
967 } | 949 } |
968 | 950 |
969 void V8Debugger::asyncTaskCandidateForStepping(void* task) { | 951 void V8Debugger::asyncTaskCandidateForStepping(void* task) { |
970 if (!m_stepIntoAsyncCallback) return; | 952 if (!m_stepIntoAsyncCallback) return; |
971 DCHECK(m_targetContextGroupId); | 953 DCHECK(m_targetContextGroupId); |
972 if (currentContextGroupId() != m_targetContextGroupId) return; | 954 if (currentContextGroupId() != m_targetContextGroupId) return; |
973 m_taskWithScheduledBreak = task; | 955 m_taskWithScheduledBreak = task; |
(...skipping 16 matching lines...) Expand all Loading... | |
990 } | 972 } |
991 | 973 |
992 void V8Debugger::asyncTaskCanceledForStepping(void* task) { | 974 void V8Debugger::asyncTaskCanceledForStepping(void* task) { |
993 if (task != m_taskWithScheduledBreak) return; | 975 if (task != m_taskWithScheduledBreak) return; |
994 m_taskWithScheduledBreak = nullptr; | 976 m_taskWithScheduledBreak = nullptr; |
995 } | 977 } |
996 | 978 |
997 void V8Debugger::allAsyncTasksCanceled() { | 979 void V8Debugger::allAsyncTasksCanceled() { |
998 m_asyncTaskStacks.clear(); | 980 m_asyncTaskStacks.clear(); |
999 m_recurringTasks.clear(); | 981 m_recurringTasks.clear(); |
1000 m_currentStacks.clear(); | 982 m_currentAsyncParent.clear(); |
1001 m_currentCreationStacks.clear(); | 983 m_currentAsyncCreation.clear(); |
1002 m_currentTasks.clear(); | 984 m_currentTasks.clear(); |
1003 m_parentTask.clear(); | 985 m_parentTask.clear(); |
1004 m_asyncTaskCreationStacks.clear(); | 986 m_asyncTaskCreationStacks.clear(); |
1005 m_idToTask.clear(); | 987 |
1006 m_taskToId.clear(); | 988 m_allAsyncStacks.clear(); |
1007 m_lastTaskId = 0; | 989 m_asyncStacksCount = 0; |
1008 } | 990 } |
1009 | 991 |
1010 void V8Debugger::muteScriptParsedEvents() { | 992 void V8Debugger::muteScriptParsedEvents() { |
1011 ++m_ignoreScriptParsedEventsCounter; | 993 ++m_ignoreScriptParsedEventsCounter; |
1012 } | 994 } |
1013 | 995 |
1014 void V8Debugger::unmuteScriptParsedEvents() { | 996 void V8Debugger::unmuteScriptParsedEvents() { |
1015 --m_ignoreScriptParsedEventsCounter; | 997 --m_ignoreScriptParsedEventsCounter; |
1016 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); | 998 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); |
1017 } | 999 } |
1018 | 1000 |
1019 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( | 1001 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
1020 bool fullStack) { | 1002 bool fullStack) { |
1021 if (!m_isolate->InContext()) return nullptr; | 1003 if (!m_isolate->InContext()) return nullptr; |
1022 | 1004 |
1023 v8::HandleScope handles(m_isolate); | 1005 v8::HandleScope handles(m_isolate); |
1024 int contextGroupId = currentContextGroupId(); | 1006 int contextGroupId = currentContextGroupId(); |
1025 if (!contextGroupId) return nullptr; | 1007 if (!contextGroupId) return nullptr; |
1026 | 1008 |
1027 size_t stackSize = | 1009 int stackSize = 1; |
1028 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 1010 if (fullStack || m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) { |
1029 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | |
1030 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1011 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
1031 | 1012 } |
1032 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1013 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
1033 } | 1014 } |
1034 | 1015 |
1035 int V8Debugger::currentContextGroupId() { | 1016 int V8Debugger::currentContextGroupId() { |
1036 if (!m_isolate->InContext()) return 0; | 1017 if (!m_isolate->InContext()) return 0; |
1037 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | 1018 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
1038 } | 1019 } |
1039 | 1020 |
1021 void V8Debugger::collectOldAsyncStacksIfNeeded() { | |
1022 if (m_asyncStacksCount < m_maxAsyncCallStacks) return; | |
1023 while (m_asyncStacksCount > m_maxAsyncCallStacks / 2) { | |
1024 m_allAsyncStacks.pop_front(); | |
1025 --m_asyncStacksCount; | |
1026 } | |
1027 removeOldAsyncTasks(m_asyncTaskStacks); | |
1028 removeOldAsyncTasks(m_asyncTaskCreationStacks); | |
1029 } | |
1030 | |
1031 void V8Debugger::removeOldAsyncTasks(AsyncTaskToStackTrace& map) { | |
1032 AsyncTaskToStackTrace cleanCopy; | |
1033 for (auto it : map) { | |
1034 if (!it.second.expired()) cleanCopy.insert(it); | |
1035 } | |
1036 map.swap(cleanCopy); | |
1037 } | |
1038 | |
1039 void V8Debugger::setMaxAsyncTaskStacksForTest(int limit) { | |
1040 m_maxAsyncCallStacks = 0; | |
1041 collectOldAsyncStacksIfNeeded(); | |
1042 m_maxAsyncCallStacks = limit; | |
1043 } | |
1044 | |
1040 } // namespace v8_inspector | 1045 } // namespace v8_inspector |
OLD | NEW |