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 static const char v8AsyncTaskEventEnqueue[] = "enqueue"; | 23 static const char v8AsyncTaskEventEnqueue[] = "enqueue"; |
24 static const char v8AsyncTaskEventEnqueueRecurring[] = "enqueueRecurring"; | 24 static const char v8AsyncTaskEventEnqueueRecurring[] = "enqueueRecurring"; |
25 static const char v8AsyncTaskEventWillHandle[] = "willHandle"; | 25 static const char v8AsyncTaskEventWillHandle[] = "willHandle"; |
26 static const char v8AsyncTaskEventDidHandle[] = "didHandle"; | 26 static const char v8AsyncTaskEventDidHandle[] = "didHandle"; |
27 static const char v8AsyncTaskEventCancel[] = "cancel"; | 27 static const char v8AsyncTaskEventCancel[] = "cancel"; |
28 | 28 |
| 29 // Based on DevTools frontend measurement, with asyncCallStackDepth = 4, |
| 30 // average async call stack tail requires ~1 Kb. Let's reserve ~ 128 Mb |
| 31 // for async stacks. |
| 32 static const int kMaxAsyncTaskStacks = 128 * 1024; |
| 33 |
29 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { | 34 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { |
30 return value ? v8::True(isolate) : v8::False(isolate); | 35 return value ? v8::True(isolate) : v8::False(isolate); |
31 } | 36 } |
32 | 37 |
33 } // namespace | 38 } // namespace |
34 | 39 |
35 static bool inLiveEditScope = false; | 40 static bool inLiveEditScope = false; |
36 | 41 |
37 v8::MaybeLocal<v8::Value> V8Debugger::callDebuggerMethod( | 42 v8::MaybeLocal<v8::Value> V8Debugger::callDebuggerMethod( |
38 const char* functionName, int argc, v8::Local<v8::Value> argv[]) { | 43 const char* functionName, int argc, v8::Local<v8::Value> argv[]) { |
(...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 int contextGroupId = | 899 int contextGroupId = |
895 m_isolate->InContext() | 900 m_isolate->InContext() |
896 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) | 901 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) |
897 : 0; | 902 : 0; |
898 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( | 903 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( |
899 this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, | 904 this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, |
900 taskName); | 905 taskName); |
901 if (chain) { | 906 if (chain) { |
902 m_asyncTaskStacks[task] = std::move(chain); | 907 m_asyncTaskStacks[task] = std::move(chain); |
903 if (recurring) m_recurringTasks.insert(task); | 908 if (recurring) m_recurringTasks.insert(task); |
| 909 m_scheduledOrder.push_back(task); |
| 910 while (m_scheduledOrder.size() - m_scheduledOrderDeleted.size() > |
| 911 kMaxAsyncTaskStacks) { |
| 912 void* task = m_scheduledOrder.front(); |
| 913 m_scheduledOrder.pop_front(); |
| 914 m_asyncTaskStacks.erase(task); |
| 915 m_recurringTasks.erase(task); |
| 916 m_scheduledOrderDeleted.erase(task); |
| 917 } |
904 } | 918 } |
905 } | 919 } |
906 | 920 |
907 void V8Debugger::asyncTaskCanceled(void* task) { | 921 void V8Debugger::asyncTaskCanceled(void* task) { |
908 if (!m_maxAsyncCallStackDepth) return; | 922 if (!m_maxAsyncCallStackDepth) return; |
909 m_asyncTaskStacks.erase(task); | 923 m_asyncTaskStacks.erase(task); |
| 924 m_scheduledOrderDeleted.insert(task); |
| 925 cleanupScheduledOrderIfNeeded(); |
910 m_recurringTasks.erase(task); | 926 m_recurringTasks.erase(task); |
911 } | 927 } |
912 | 928 |
913 void V8Debugger::asyncTaskStarted(void* task) { | 929 void V8Debugger::asyncTaskStarted(void* task) { |
914 if (!m_maxAsyncCallStackDepth) return; | 930 if (!m_maxAsyncCallStackDepth) return; |
915 m_currentTasks.push_back(task); | 931 m_currentTasks.push_back(task); |
916 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(task); | 932 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(task); |
917 // Needs to support following order of events: | 933 // Needs to support following order of events: |
918 // - asyncTaskScheduled | 934 // - asyncTaskScheduled |
919 // <-- attached here --> | 935 // <-- attached here --> |
920 // - asyncTaskStarted | 936 // - asyncTaskStarted |
921 // - asyncTaskCanceled <-- canceled before finished | 937 // - asyncTaskCanceled <-- canceled before finished |
922 // <-- async stack requested here --> | 938 // <-- async stack requested here --> |
923 // - asyncTaskFinished | 939 // - asyncTaskFinished |
924 std::unique_ptr<V8StackTraceImpl> stack; | 940 std::unique_ptr<V8StackTraceImpl> stack; |
925 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) | 941 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) |
926 stack = stackIt->second->cloneImpl(); | 942 stack = stackIt->second->cloneImpl(); |
927 m_currentStacks.push_back(std::move(stack)); | 943 m_currentStacks.push_back(std::move(stack)); |
928 } | 944 } |
929 | 945 |
930 void V8Debugger::asyncTaskFinished(void* task) { | 946 void V8Debugger::asyncTaskFinished(void* task) { |
931 if (!m_maxAsyncCallStackDepth) return; | 947 if (!m_maxAsyncCallStackDepth) return; |
932 // We could start instrumenting half way and the stack is empty. | 948 // We could start instrumenting half way and the stack is empty. |
933 if (!m_currentStacks.size()) return; | 949 if (!m_currentStacks.size()) return; |
934 | 950 |
935 DCHECK(m_currentTasks.back() == task); | 951 DCHECK(m_currentTasks.back() == task); |
936 m_currentTasks.pop_back(); | 952 m_currentTasks.pop_back(); |
937 | 953 |
938 m_currentStacks.pop_back(); | 954 m_currentStacks.pop_back(); |
939 if (m_recurringTasks.find(task) == m_recurringTasks.end()) | 955 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { |
940 m_asyncTaskStacks.erase(task); | 956 m_asyncTaskStacks.erase(task); |
| 957 m_scheduledOrderDeleted.insert(task); |
| 958 cleanupScheduledOrderIfNeeded(); |
| 959 } |
941 } | 960 } |
942 | 961 |
943 void V8Debugger::allAsyncTasksCanceled() { | 962 void V8Debugger::allAsyncTasksCanceled() { |
944 m_asyncTaskStacks.clear(); | 963 m_asyncTaskStacks.clear(); |
| 964 m_scheduledOrder.clear(); |
| 965 m_scheduledOrderDeleted.clear(); |
945 m_recurringTasks.clear(); | 966 m_recurringTasks.clear(); |
946 m_currentStacks.clear(); | 967 m_currentStacks.clear(); |
947 m_currentTasks.clear(); | 968 m_currentTasks.clear(); |
948 } | 969 } |
949 | 970 |
| 971 void V8Debugger::cleanupScheduledOrderIfNeeded() { |
| 972 if (m_scheduledOrder.size() < kMaxAsyncTaskStacks * 2) return; |
| 973 std::deque<void*> scheduledOrder; |
| 974 for (void* task : m_scheduledOrder) { |
| 975 if (m_scheduledOrderDeleted.find(task) == m_scheduledOrderDeleted.end()) { |
| 976 scheduledOrder.push_back(task); |
| 977 } |
| 978 } |
| 979 m_scheduledOrder.swap(scheduledOrder); |
| 980 m_scheduledOrderDeleted.clear(); |
| 981 } |
| 982 |
950 void V8Debugger::muteScriptParsedEvents() { | 983 void V8Debugger::muteScriptParsedEvents() { |
951 ++m_ignoreScriptParsedEventsCounter; | 984 ++m_ignoreScriptParsedEventsCounter; |
952 } | 985 } |
953 | 986 |
954 void V8Debugger::unmuteScriptParsedEvents() { | 987 void V8Debugger::unmuteScriptParsedEvents() { |
955 --m_ignoreScriptParsedEventsCounter; | 988 --m_ignoreScriptParsedEventsCounter; |
956 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); | 989 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); |
957 } | 990 } |
958 | 991 |
959 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( | 992 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
960 bool fullStack) { | 993 bool fullStack) { |
961 if (!m_isolate->InContext()) return nullptr; | 994 if (!m_isolate->InContext()) return nullptr; |
962 | 995 |
963 v8::HandleScope handles(m_isolate); | 996 v8::HandleScope handles(m_isolate); |
964 int contextGroupId = | 997 int contextGroupId = |
965 m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | 998 m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
966 if (!contextGroupId) return nullptr; | 999 if (!contextGroupId) return nullptr; |
967 | 1000 |
968 size_t stackSize = | 1001 size_t stackSize = |
969 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 1002 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
970 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 1003 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
971 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1004 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
972 | 1005 |
973 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1006 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
974 } | 1007 } |
975 | 1008 |
976 } // namespace v8_inspector | 1009 } // namespace v8_inspector |
OLD | NEW |