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

Side by Side Diff: src/inspector/v8-debugger.cc

Issue 2816043006: [inspector] avoid cloning of async call chains (Closed)
Patch Set: StackTrace -> back to V8StacktraceImpl Created 3 years, 8 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
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698