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

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

Issue 2816043006: [inspector] avoid cloning of async call chains (Closed)
Patch Set: rebased 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 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 } 637 }
642 638
643 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, 639 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type,
644 int id, int parentId, 640 int id, int parentId,
645 bool createdByUser) { 641 bool createdByUser) {
646 // Async task events from Promises are given misaligned pointers to prevent 642 // Async task events from Promises are given misaligned pointers to prevent
647 // from overlapping with other Blink task identifiers. 643 // from overlapping with other Blink task identifiers.
648 void* task = reinterpret_cast<void*>(id * 2 + 1); 644 void* task = reinterpret_cast<void*>(id * 2 + 1);
649 void* parentTask = 645 void* parentTask =
650 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; 646 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr;
647 if (type == v8::debug::kDebugPromiseCollected) {
dgozman 2017/04/17 23:03:15 Undo this part now.
kozy 2017/04/18 01:04:38 Done.
648 asyncTaskCanceledForStack(task);
649 asyncTaskCanceledForStepping(task);
650 return;
651 }
651 switch (type) { 652 switch (type) {
652 case v8::debug::kDebugPromiseCreated: 653 case v8::debug::kDebugPromiseCreated:
653 asyncTaskCreatedForStack(task, parentTask); 654 asyncTaskCreatedForStack(task, parentTask);
654 if (createdByUser && parentTask) asyncTaskCandidateForStepping(task); 655 if (createdByUser && parentTask) asyncTaskCandidateForStepping(task);
655 break; 656 break;
656 case v8::debug::kDebugEnqueueAsyncFunction: 657 case v8::debug::kDebugEnqueueAsyncFunction:
657 asyncTaskScheduledForStack("async function", task, true); 658 asyncTaskScheduledForStack("async function", task, true);
658 break; 659 break;
659 case v8::debug::kDebugEnqueuePromiseResolve: 660 case v8::debug::kDebugEnqueuePromiseResolve:
660 asyncTaskScheduledForStack("Promise.resolve", task, true); 661 asyncTaskScheduledForStack("Promise.resolve", task, true);
661 break; 662 break;
662 case v8::debug::kDebugEnqueuePromiseReject: 663 case v8::debug::kDebugEnqueuePromiseReject:
663 asyncTaskScheduledForStack("Promise.reject", task, true); 664 asyncTaskScheduledForStack("Promise.reject", task, true);
664 break; 665 break;
665 case v8::debug::kDebugPromiseCollected:
666 asyncTaskCanceledForStack(task);
667 asyncTaskCanceledForStepping(task);
668 break;
669 case v8::debug::kDebugWillHandle: 666 case v8::debug::kDebugWillHandle:
670 asyncTaskStartedForStack(task); 667 asyncTaskStartedForStack(task);
671 asyncTaskStartedForStepping(task); 668 asyncTaskStartedForStepping(task);
672 break; 669 break;
673 case v8::debug::kDebugDidHandle: 670 case v8::debug::kDebugDidHandle:
674 asyncTaskFinishedForStack(task); 671 asyncTaskFinishedForStack(task);
675 asyncTaskFinishedForStepping(task); 672 asyncTaskFinishedForStepping(task);
676 break; 673 break;
674 case v8::debug::kDebugPromiseCollected:
675 UNREACHABLE();
676 break;
677 } 677 }
678 } 678 }
679 679
680 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { 680 std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncParent() {
681 if (!m_currentStacks.size()) return nullptr; 681 return m_currentAsyncParent.empty() ? nullptr : m_currentAsyncParent.back();
682 return m_currentStacks.back().get();
683 } 682 }
684 683
685 V8StackTraceImpl* V8Debugger::currentAsyncTaskCreationStack() { 684 std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncCreation() {
686 if (!m_currentCreationStacks.size()) return nullptr; 685 return m_currentAsyncCreation.empty() ? nullptr
687 return m_currentCreationStacks.back().get(); 686 : m_currentAsyncCreation.back();
688 } 687 }
689 688
690 void V8Debugger::compileDebuggerScript() { 689 void V8Debugger::compileDebuggerScript() {
691 if (!m_debuggerScript.IsEmpty()) { 690 if (!m_debuggerScript.IsEmpty()) {
692 UNREACHABLE(); 691 UNREACHABLE();
693 return; 692 return;
694 } 693 }
695 694
696 v8::HandleScope scope(m_isolate); 695 v8::HandleScope scope(m_isolate);
697 v8::Context::Scope contextScope(debuggerContext()); 696 v8::Context::Scope contextScope(debuggerContext());
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 functionScopes(context, function).ToLocal(&scopes)) { 817 functionScopes(context, function).ToLocal(&scopes)) {
819 createDataProperty(context, properties, properties->Length(), 818 createDataProperty(context, properties, properties->Length(),
820 toV8StringInternalized(m_isolate, "[[Scopes]]")); 819 toV8StringInternalized(m_isolate, "[[Scopes]]"));
821 createDataProperty(context, properties, properties->Length(), scopes); 820 createDataProperty(context, properties, properties->Length(), scopes);
822 } 821 }
823 } 822 }
824 return properties; 823 return properties;
825 } 824 }
826 825
827 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( 826 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace(
828 v8::Local<v8::StackTrace> stackTrace) { 827 v8::Local<v8::StackTrace> v8StackTrace) {
829 return V8StackTraceImpl::create(this, currentContextGroupId(), stackTrace, 828 return V8StackTraceImpl::create(this, currentContextGroupId(), v8StackTrace,
830 V8StackTraceImpl::maxCallStackSizeToCapture); 829 V8StackTraceImpl::maxCallStackSizeToCapture);
831 } 830 }
832 831
833 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { 832 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) {
834 if (depth <= 0) 833 if (depth <= 0)
835 m_maxAsyncCallStackDepthMap.erase(agent); 834 m_maxAsyncCallStackDepthMap.erase(agent);
836 else 835 else
837 m_maxAsyncCallStackDepthMap[agent] = depth; 836 m_maxAsyncCallStackDepthMap[agent] = depth;
838 837
839 int maxAsyncCallStackDepth = 0; 838 int maxAsyncCallStackDepth = 0;
840 for (const auto& pair : m_maxAsyncCallStackDepthMap) { 839 for (const auto& pair : m_maxAsyncCallStackDepthMap) {
841 if (pair.second > maxAsyncCallStackDepth) 840 if (pair.second > maxAsyncCallStackDepth)
842 maxAsyncCallStackDepth = pair.second; 841 maxAsyncCallStackDepth = pair.second;
843 } 842 }
844 843
845 if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) return; 844 if (m_maxAsyncCallStackDepth == maxAsyncCallStackDepth) return;
846 m_maxAsyncCallStackDepth = maxAsyncCallStackDepth; 845 m_maxAsyncCallStackDepth = maxAsyncCallStackDepth;
847 if (!maxAsyncCallStackDepth) allAsyncTasksCanceled(); 846 if (!maxAsyncCallStackDepth) allAsyncTasksCanceled();
848 } 847 }
849 848
850 void V8Debugger::registerAsyncTaskIfNeeded(void* task) {
851 if (m_taskToId.find(task) != m_taskToId.end()) return;
852
853 int id = ++m_lastTaskId;
854 m_taskToId[task] = id;
855 m_idToTask[id] = task;
856 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) {
857 void* taskToRemove = m_idToTask.begin()->second;
858 asyncTaskCanceledForStack(taskToRemove);
859 }
860 }
861
862 void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) { 849 void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) {
863 if (!m_maxAsyncCallStackDepth) return; 850 if (!m_maxAsyncCallStackDepth) return;
864 if (parentTask) m_parentTask[task] = parentTask; 851 if (parentTask) m_parentTask[task] = parentTask;
865 v8::HandleScope scope(m_isolate); 852 v8::HandleScope scope(m_isolate);
866 // We don't need to pass context group id here because we get this callback 853 std::shared_ptr<AsyncStackTrace> asyncCreation =
867 // from V8 for promise events only. 854 AsyncStackTrace::capture(this, currentContextGroupId(), String16(), 1);
868 // Passing one as maxStackSize forces no async chain for the new stack and 855 // Passing one as maxStackSize forces no async chain for the new stack.
869 // allows us to not grow exponentially. 856 if (asyncCreation && !asyncCreation->isEmpty()) {
870 std::unique_ptr<V8StackTraceImpl> creationStack = 857 m_asyncTaskCreationStacks[task] = asyncCreation;
871 V8StackTraceImpl::capture(this, 0, 1, String16()); 858 m_allAsyncStacks.push_back(asyncCreation);
872 if (creationStack && !creationStack->isEmpty()) { 859 ++m_asyncStacksCount;
873 m_asyncTaskCreationStacks[task] = std::move(creationStack); 860 collectOldAsyncStacksIfNeeded();
874 registerAsyncTaskIfNeeded(task);
875 } 861 }
876 } 862 }
877 863
878 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, 864 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task,
879 bool recurring) { 865 bool recurring) {
880 asyncTaskScheduledForStack(toString16(taskName), task, recurring); 866 asyncTaskScheduledForStack(toString16(taskName), task, recurring);
881 asyncTaskCandidateForStepping(task); 867 asyncTaskCandidateForStepping(task);
882 } 868 }
883 869
884 void V8Debugger::asyncTaskCanceled(void* task) { 870 void V8Debugger::asyncTaskCanceled(void* task) {
885 asyncTaskCanceledForStack(task); 871 asyncTaskCanceledForStack(task);
886 asyncTaskCanceledForStepping(task); 872 asyncTaskCanceledForStepping(task);
887 } 873 }
888 874
889 void V8Debugger::asyncTaskStarted(void* task) { 875 void V8Debugger::asyncTaskStarted(void* task) {
890 asyncTaskStartedForStack(task); 876 asyncTaskStartedForStack(task);
891 asyncTaskStartedForStepping(task); 877 asyncTaskStartedForStepping(task);
892 } 878 }
893 879
894 void V8Debugger::asyncTaskFinished(void* task) { 880 void V8Debugger::asyncTaskFinished(void* task) {
895 asyncTaskFinishedForStack(task); 881 asyncTaskFinishedForStack(task);
896 asyncTaskFinishedForStepping(task); 882 asyncTaskFinishedForStepping(task);
897 } 883 }
898 884
899 void V8Debugger::asyncTaskScheduledForStack(const String16& taskName, 885 void V8Debugger::asyncTaskScheduledForStack(const String16& taskName,
900 void* task, bool recurring) { 886 void* task, bool recurring) {
901 if (!m_maxAsyncCallStackDepth) return; 887 if (!m_maxAsyncCallStackDepth) return;
902 v8::HandleScope scope(m_isolate); 888 v8::HandleScope scope(m_isolate);
903 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( 889 std::shared_ptr<AsyncStackTrace> asyncStack =
904 this, currentContextGroupId(), 890 AsyncStackTrace::capture(this, currentContextGroupId(), taskName,
905 V8StackTraceImpl::maxCallStackSizeToCapture, taskName); 891 V8StackTraceImpl::maxCallStackSizeToCapture);
906 if (chain) { 892 if (asyncStack) {
907 m_asyncTaskStacks[task] = std::move(chain); 893 m_asyncTaskStacks[task] = asyncStack;
908 if (recurring) m_recurringTasks.insert(task); 894 if (recurring) m_recurringTasks.insert(task);
909 registerAsyncTaskIfNeeded(task); 895
896 m_allAsyncStacks.push_back(asyncStack);
897 ++m_asyncStacksCount;
898 collectOldAsyncStacksIfNeeded();
910 } 899 }
911 } 900 }
912 901
913 void V8Debugger::asyncTaskCanceledForStack(void* task) { 902 void V8Debugger::asyncTaskCanceledForStack(void* task) {
914 if (!m_maxAsyncCallStackDepth) return; 903 if (!m_maxAsyncCallStackDepth) return;
915 m_asyncTaskStacks.erase(task); 904 m_asyncTaskStacks.erase(task);
916 m_recurringTasks.erase(task); 905 m_recurringTasks.erase(task);
917 m_parentTask.erase(task); 906 m_parentTask.erase(task);
918 m_asyncTaskCreationStacks.erase(task); 907 m_asyncTaskCreationStacks.erase(task);
919 auto it = m_taskToId.find(task);
920 if (it == m_taskToId.end()) return;
921 m_idToTask.erase(it->second);
922 m_taskToId.erase(it);
923 } 908 }
924 909
925 void V8Debugger::asyncTaskStartedForStack(void* task) { 910 void V8Debugger::asyncTaskStartedForStack(void* task) {
926 if (!m_maxAsyncCallStackDepth) return; 911 if (!m_maxAsyncCallStackDepth) return;
927 m_currentTasks.push_back(task); 912 m_currentTasks.push_back(task);
928 auto parentIt = m_parentTask.find(task); 913 auto parentIt = m_parentTask.find(task);
929 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( 914 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(
930 parentIt == m_parentTask.end() ? task : parentIt->second); 915 parentIt == m_parentTask.end() ? task : parentIt->second);
931 // Needs to support following order of events: 916 // Needs to support following order of events:
932 // - asyncTaskScheduled 917 // - asyncTaskScheduled
933 // <-- attached here --> 918 // <-- attached here -->
934 // - asyncTaskStarted 919 // - asyncTaskStarted
935 // - asyncTaskCanceled <-- canceled before finished 920 // - asyncTaskCanceled <-- canceled before finished
936 // <-- async stack requested here --> 921 // <-- async stack requested here -->
937 // - asyncTaskFinished 922 // - asyncTaskFinished
938 std::unique_ptr<V8StackTraceImpl> stack; 923 std::shared_ptr<AsyncStackTrace> asyncParent;
939 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) 924 if (stackIt != m_asyncTaskStacks.end()) asyncParent = stackIt->second.lock();
940 stack = stackIt->second->cloneImpl();
941 auto itCreation = m_asyncTaskCreationStacks.find(task); 925 auto itCreation = m_asyncTaskCreationStacks.find(task);
942 if (stack && itCreation != m_asyncTaskCreationStacks.end()) { 926 if (asyncParent && itCreation != m_asyncTaskCreationStacks.end()) {
943 m_currentCreationStacks.push_back(itCreation->second->cloneImpl()); 927 m_currentAsyncCreation.push_back(itCreation->second.lock());
944 } else { 928 } else {
945 m_currentCreationStacks.push_back(nullptr); 929 m_currentAsyncCreation.push_back(nullptr);
946 } 930 }
947 m_currentStacks.push_back(std::move(stack)); 931 m_currentAsyncParent.push_back(asyncParent);
948 } 932 }
949 933
950 void V8Debugger::asyncTaskFinishedForStack(void* task) { 934 void V8Debugger::asyncTaskFinishedForStack(void* task) {
951 if (!m_maxAsyncCallStackDepth) return; 935 if (!m_maxAsyncCallStackDepth) return;
952 // We could start instrumenting half way and the stack is empty. 936 // We could start instrumenting half way and the stack is empty.
953 if (!m_currentStacks.size()) return; 937 if (!m_currentTasks.size()) return;
954 DCHECK(m_currentTasks.back() == task); 938 DCHECK(m_currentTasks.back() == task);
955 m_currentTasks.pop_back(); 939 m_currentTasks.pop_back();
956 940
957 DCHECK(m_currentStacks.size() == m_currentCreationStacks.size()); 941 DCHECK(m_currentAsyncParent.size() == m_currentAsyncCreation.size());
958 m_currentStacks.pop_back(); 942 m_currentAsyncParent.pop_back();
959 m_currentCreationStacks.pop_back(); 943 m_currentAsyncCreation.pop_back();
944
960 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { 945 if (m_recurringTasks.find(task) == m_recurringTasks.end()) {
961 asyncTaskCanceledForStack(task); 946 asyncTaskCanceledForStack(task);
962 } 947 }
963 } 948 }
964 949
965 void V8Debugger::asyncTaskCandidateForStepping(void* task) { 950 void V8Debugger::asyncTaskCandidateForStepping(void* task) {
966 if (!m_stepIntoAsyncCallback) return; 951 if (!m_stepIntoAsyncCallback) return;
967 DCHECK(m_targetContextGroupId); 952 DCHECK(m_targetContextGroupId);
968 if (currentContextGroupId() != m_targetContextGroupId) return; 953 if (currentContextGroupId() != m_targetContextGroupId) return;
969 m_taskWithScheduledBreak = task; 954 m_taskWithScheduledBreak = task;
(...skipping 16 matching lines...) Expand all
986 } 971 }
987 972
988 void V8Debugger::asyncTaskCanceledForStepping(void* task) { 973 void V8Debugger::asyncTaskCanceledForStepping(void* task) {
989 if (task != m_taskWithScheduledBreak) return; 974 if (task != m_taskWithScheduledBreak) return;
990 m_taskWithScheduledBreak = nullptr; 975 m_taskWithScheduledBreak = nullptr;
991 } 976 }
992 977
993 void V8Debugger::allAsyncTasksCanceled() { 978 void V8Debugger::allAsyncTasksCanceled() {
994 m_asyncTaskStacks.clear(); 979 m_asyncTaskStacks.clear();
995 m_recurringTasks.clear(); 980 m_recurringTasks.clear();
996 m_currentStacks.clear(); 981 m_currentAsyncParent.clear();
997 m_currentCreationStacks.clear(); 982 m_currentAsyncCreation.clear();
998 m_currentTasks.clear(); 983 m_currentTasks.clear();
999 m_parentTask.clear(); 984 m_parentTask.clear();
1000 m_asyncTaskCreationStacks.clear(); 985 m_asyncTaskCreationStacks.clear();
1001 m_idToTask.clear(); 986
1002 m_taskToId.clear(); 987 m_allAsyncStacks.clear();
1003 m_lastTaskId = 0; 988 m_asyncStacksCount = 0;
1004 } 989 }
1005 990
1006 void V8Debugger::muteScriptParsedEvents() { 991 void V8Debugger::muteScriptParsedEvents() {
1007 ++m_ignoreScriptParsedEventsCounter; 992 ++m_ignoreScriptParsedEventsCounter;
1008 } 993 }
1009 994
1010 void V8Debugger::unmuteScriptParsedEvents() { 995 void V8Debugger::unmuteScriptParsedEvents() {
1011 --m_ignoreScriptParsedEventsCounter; 996 --m_ignoreScriptParsedEventsCounter;
1012 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); 997 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0);
1013 } 998 }
1014 999
1015 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( 1000 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace(
1016 bool fullStack) { 1001 bool fullStack) {
1017 if (!m_isolate->InContext()) return nullptr; 1002 if (!m_isolate->InContext()) return nullptr;
1018 1003
1019 v8::HandleScope handles(m_isolate); 1004 v8::HandleScope handles(m_isolate);
1020 int contextGroupId = currentContextGroupId(); 1005 int contextGroupId = currentContextGroupId();
1021 if (!contextGroupId) return nullptr; 1006 if (!contextGroupId) return nullptr;
1022 1007
1023 size_t stackSize = 1008 int stackSize = 1;
1024 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; 1009 if (fullStack || m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) {
1025 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId))
1026 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; 1010 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture;
1027 1011 }
1028 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); 1012 return V8StackTraceImpl::capture(this, contextGroupId, stackSize);
1029 } 1013 }
1030 1014
1031 int V8Debugger::currentContextGroupId() { 1015 int V8Debugger::currentContextGroupId() {
1032 if (!m_isolate->InContext()) return 0; 1016 if (!m_isolate->InContext()) return 0;
1033 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); 1017 return m_inspector->contextGroupId(m_isolate->GetCurrentContext());
1034 } 1018 }
1035 1019
1020 void V8Debugger::collectOldAsyncStacksIfNeeded() {
1021 if (m_asyncStacksCount <= m_maxAsyncCallStacks) return;
1022 while (m_asyncStacksCount >
1023 m_maxAsyncCallStacks / 2 + m_maxAsyncCallStacks % 2) {
dgozman 2017/04/17 23:03:15 nit: extract a variable for this.
kozy 2017/04/18 01:04:38 Done.
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
1036 } // namespace v8_inspector 1045 } // namespace v8_inspector
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698