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 static const int kMaxAsyncTaskStacks = 1024 * 1024; | 24 static const int kMaxAsyncTaskStacks = 128 * 1024; |
25 | 25 |
26 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { | 26 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { |
27 return value ? v8::True(isolate) : v8::False(isolate); | 27 return value ? v8::True(isolate) : v8::False(isolate); |
28 } | 28 } |
29 | 29 |
30 V8DebuggerAgentImpl* agentForScript(V8InspectorImpl* inspector, | 30 V8DebuggerAgentImpl* agentForScript(V8InspectorImpl* inspector, |
31 v8::Local<v8::debug::Script> script) { | 31 v8::Local<v8::debug::Script> script) { |
32 v8::Local<v8::Value> contextData; | 32 v8::Local<v8::Value> contextData; |
33 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) { | 33 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) { |
34 return nullptr; | 34 return nullptr; |
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
844 | 844 |
845 void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) { | 845 void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) { |
846 if (!m_maxAsyncCallStackDepth) return; | 846 if (!m_maxAsyncCallStackDepth) return; |
847 if (parentTask) m_parentTask[task] = parentTask; | 847 if (parentTask) m_parentTask[task] = parentTask; |
848 v8::HandleScope scope(m_isolate); | 848 v8::HandleScope scope(m_isolate); |
849 std::shared_ptr<AsyncStackTrace> asyncCreation = | 849 std::shared_ptr<AsyncStackTrace> asyncCreation = |
850 AsyncStackTrace::capture(this, currentContextGroupId(), String16(), 1); | 850 AsyncStackTrace::capture(this, currentContextGroupId(), String16(), 1); |
851 // Passing one as maxStackSize forces no async chain for the new stack. | 851 // Passing one as maxStackSize forces no async chain for the new stack. |
852 if (asyncCreation && !asyncCreation->isEmpty()) { | 852 if (asyncCreation && !asyncCreation->isEmpty()) { |
853 m_asyncTaskCreationStacks[task] = asyncCreation; | 853 m_asyncTaskCreationStacks[task] = asyncCreation; |
854 m_allAsyncStacks.push_back(asyncCreation); | 854 m_allAsyncStacks.push_back(std::move(asyncCreation)); |
855 ++m_asyncStacksCount; | 855 ++m_asyncStacksCount; |
856 collectOldAsyncStacksIfNeeded(); | 856 collectOldAsyncStacksIfNeeded(); |
857 } | 857 } |
858 } | 858 } |
859 | 859 |
860 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, | 860 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
861 bool recurring) { | 861 bool recurring) { |
862 asyncTaskScheduledForStack(toString16(taskName), task, recurring); | 862 asyncTaskScheduledForStack(toString16(taskName), task, recurring); |
863 asyncTaskCandidateForStepping(task); | 863 asyncTaskCandidateForStepping(task); |
864 } | 864 } |
(...skipping 16 matching lines...) Expand all Loading... | |
881 void V8Debugger::asyncTaskScheduledForStack(const String16& taskName, | 881 void V8Debugger::asyncTaskScheduledForStack(const String16& taskName, |
882 void* task, bool recurring) { | 882 void* task, bool recurring) { |
883 if (!m_maxAsyncCallStackDepth) return; | 883 if (!m_maxAsyncCallStackDepth) return; |
884 v8::HandleScope scope(m_isolate); | 884 v8::HandleScope scope(m_isolate); |
885 std::shared_ptr<AsyncStackTrace> asyncStack = | 885 std::shared_ptr<AsyncStackTrace> asyncStack = |
886 AsyncStackTrace::capture(this, currentContextGroupId(), taskName, | 886 AsyncStackTrace::capture(this, currentContextGroupId(), taskName, |
887 V8StackTraceImpl::maxCallStackSizeToCapture); | 887 V8StackTraceImpl::maxCallStackSizeToCapture); |
888 if (asyncStack) { | 888 if (asyncStack) { |
889 m_asyncTaskStacks[task] = asyncStack; | 889 m_asyncTaskStacks[task] = asyncStack; |
890 if (recurring) m_recurringTasks.insert(task); | 890 if (recurring) m_recurringTasks.insert(task); |
891 | 891 m_allAsyncStacks.push_back(std::move(asyncStack)); |
892 m_allAsyncStacks.push_back(asyncStack); | |
893 ++m_asyncStacksCount; | 892 ++m_asyncStacksCount; |
894 collectOldAsyncStacksIfNeeded(); | 893 collectOldAsyncStacksIfNeeded(); |
895 } | 894 } |
896 } | 895 } |
897 | 896 |
898 void V8Debugger::asyncTaskCanceledForStack(void* task) { | 897 void V8Debugger::asyncTaskCanceledForStack(void* task) { |
899 if (!m_maxAsyncCallStackDepth) return; | 898 if (!m_maxAsyncCallStackDepth) return; |
900 m_asyncTaskStacks.erase(task); | 899 m_asyncTaskStacks.erase(task); |
901 m_recurringTasks.erase(task); | 900 m_recurringTasks.erase(task); |
902 m_parentTask.erase(task); | 901 m_parentTask.erase(task); |
903 m_asyncTaskCreationStacks.erase(task); | 902 m_asyncTaskCreationStacks.erase(task); |
904 } | 903 } |
905 | 904 |
906 void V8Debugger::asyncTaskStartedForStack(void* task) { | 905 void V8Debugger::asyncTaskStartedForStack(void* task) { |
907 if (!m_maxAsyncCallStackDepth) return; | 906 if (!m_maxAsyncCallStackDepth) return; |
908 m_currentTasks.push_back(task); | 907 m_currentTasks.push_back(task); |
909 auto parentIt = m_parentTask.find(task); | 908 auto parentIt = m_parentTask.find(task); |
910 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( | 909 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( |
911 parentIt == m_parentTask.end() ? task : parentIt->second); | 910 parentIt == m_parentTask.end() ? task : parentIt->second); |
912 // Needs to support following order of events: | 911 // Needs to support following order of events: |
913 // - asyncTaskScheduled | 912 // - asyncTaskScheduled |
914 // <-- attached here --> | 913 // <-- attached here --> |
915 // - asyncTaskStarted | 914 // - asyncTaskStarted |
916 // - asyncTaskCanceled <-- canceled before finished | 915 // - asyncTaskCanceled <-- canceled before finished |
917 // <-- async stack requested here --> | 916 // <-- async stack requested here --> |
918 // - asyncTaskFinished | 917 // - asyncTaskFinished |
919 std::shared_ptr<AsyncStackTrace> asyncParent; | 918 std::weak_ptr<AsyncStackTrace> asyncParent; |
920 if (stackIt != m_asyncTaskStacks.end()) asyncParent = stackIt->second.lock(); | 919 if (stackIt != m_asyncTaskStacks.end()) asyncParent = stackIt->second; |
921 auto itCreation = m_asyncTaskCreationStacks.find(task); | 920 auto itCreation = m_asyncTaskCreationStacks.find(task); |
922 if (asyncParent && itCreation != m_asyncTaskCreationStacks.end()) { | 921 if (asyncParent.lock() && itCreation != m_asyncTaskCreationStacks.end()) { |
923 m_currentAsyncCreation.push_back(itCreation->second.lock()); | 922 m_currentAsyncCreation.push_back(itCreation->second.lock()); |
924 } else { | 923 } else { |
925 m_currentAsyncCreation.push_back(nullptr); | 924 m_currentAsyncCreation.emplace_back(); |
926 } | 925 } |
927 m_currentAsyncParent.push_back(asyncParent); | 926 m_currentAsyncParent.push_back(asyncParent.lock()); |
928 } | 927 } |
929 | 928 |
930 void V8Debugger::asyncTaskFinishedForStack(void* task) { | 929 void V8Debugger::asyncTaskFinishedForStack(void* task) { |
931 if (!m_maxAsyncCallStackDepth) return; | 930 if (!m_maxAsyncCallStackDepth) return; |
932 // We could start instrumenting half way and the stack is empty. | 931 // We could start instrumenting half way and the stack is empty. |
933 if (!m_currentTasks.size()) return; | 932 if (!m_currentTasks.size()) return; |
934 DCHECK(m_currentTasks.back() == task); | 933 DCHECK(m_currentTasks.back() == task); |
935 m_currentTasks.pop_back(); | 934 m_currentTasks.pop_back(); |
936 | 935 |
937 DCHECK(m_currentAsyncParent.size() == m_currentAsyncCreation.size()); | 936 DCHECK(m_currentAsyncParent.size() == m_currentAsyncCreation.size()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1016 void V8Debugger::collectOldAsyncStacksIfNeeded() { | 1015 void V8Debugger::collectOldAsyncStacksIfNeeded() { |
1017 if (m_asyncStacksCount <= m_maxAsyncCallStacks) return; | 1016 if (m_asyncStacksCount <= m_maxAsyncCallStacks) return; |
1018 int halfOfLimitRoundedUp = | 1017 int halfOfLimitRoundedUp = |
1019 m_maxAsyncCallStacks / 2 + m_maxAsyncCallStacks % 2; | 1018 m_maxAsyncCallStacks / 2 + m_maxAsyncCallStacks % 2; |
1020 while (m_asyncStacksCount > halfOfLimitRoundedUp) { | 1019 while (m_asyncStacksCount > halfOfLimitRoundedUp) { |
1021 m_allAsyncStacks.pop_front(); | 1020 m_allAsyncStacks.pop_front(); |
1022 --m_asyncStacksCount; | 1021 --m_asyncStacksCount; |
1023 } | 1022 } |
1024 removeOldAsyncTasks(m_asyncTaskStacks); | 1023 removeOldAsyncTasks(m_asyncTaskStacks); |
1025 removeOldAsyncTasks(m_asyncTaskCreationStacks); | 1024 removeOldAsyncTasks(m_asyncTaskCreationStacks); |
1025 protocol::HashSet<void*> recurringLeft; | |
1026 for (auto task : m_recurringTasks) { | |
1027 if (m_asyncTaskStacks.find(task) == m_asyncTaskStacks.end()) continue; | |
1028 recurringLeft.insert(task); | |
1029 } | |
1030 m_recurringTasks.swap(recurringLeft); | |
1031 protocol::HashMap<void*, void*> parentLeft; | |
1032 for (auto it : m_parentTask) { | |
1033 if (m_asyncTaskCreationStacks.find(it.second) == m_asyncTaskStacks.end()) { | |
dgozman
2017/04/20 00:42:23
You are comparing iterator from one map to another
kozy
2017/04/20 00:59:02
C++ is my best friend since it allows it :)
fixed:
| |
1034 continue; | |
1035 } | |
1036 parentLeft.insert(it); | |
1037 } | |
1038 m_parentTask.swap(parentLeft); | |
1026 } | 1039 } |
1027 | 1040 |
1028 void V8Debugger::removeOldAsyncTasks(AsyncTaskToStackTrace& map) { | 1041 void V8Debugger::removeOldAsyncTasks(AsyncTaskToStackTrace& map) { |
1029 AsyncTaskToStackTrace cleanCopy; | 1042 AsyncTaskToStackTrace cleanCopy; |
1030 for (auto it : map) { | 1043 for (auto it : map) { |
1031 if (!it.second.expired()) cleanCopy.insert(it); | 1044 if (!it.second.expired()) cleanCopy.insert(it); |
1032 } | 1045 } |
1033 map.swap(cleanCopy); | 1046 map.swap(cleanCopy); |
1034 } | 1047 } |
1035 | 1048 |
1036 void V8Debugger::setMaxAsyncTaskStacksForTest(int limit) { | 1049 void V8Debugger::setMaxAsyncTaskStacksForTest(int limit) { |
1037 m_maxAsyncCallStacks = 0; | 1050 m_maxAsyncCallStacks = 0; |
1038 collectOldAsyncStacksIfNeeded(); | 1051 collectOldAsyncStacksIfNeeded(); |
1039 m_maxAsyncCallStacks = limit; | 1052 m_maxAsyncCallStacks = limit; |
1040 } | 1053 } |
1041 | 1054 |
1042 } // namespace v8_inspector | 1055 } // namespace v8_inspector |
OLD | NEW |