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[]) { |
39 v8::MicrotasksScope microtasks(m_isolate, | 44 v8::MicrotasksScope microtasks(m_isolate, |
40 v8::MicrotasksScope::kDoNotRunMicrotasks); | 45 v8::MicrotasksScope::kDoNotRunMicrotasks); |
41 DCHECK(m_isolate->InContext()); | 46 DCHECK(m_isolate->InContext()); |
42 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); | 47 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); |
43 v8::Local<v8::Object> debuggerScript = m_debuggerScript.Get(m_isolate); | 48 v8::Local<v8::Object> debuggerScript = m_debuggerScript.Get(m_isolate); |
44 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( | 49 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
45 debuggerScript | 50 debuggerScript |
46 ->Get(context, toV8StringInternalized(m_isolate, functionName)) | 51 ->Get(context, toV8StringInternalized(m_isolate, functionName)) |
47 .ToLocalChecked()); | 52 .ToLocalChecked()); |
48 return function->Call(context, debuggerScript, argc, argv); | 53 return function->Call(context, debuggerScript, argc, argv); |
49 } | 54 } |
50 | 55 |
51 V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) | 56 V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) |
52 : m_isolate(isolate), | 57 : m_isolate(isolate), |
53 m_inspector(inspector), | 58 m_inspector(inspector), |
54 m_enableCount(0), | 59 m_enableCount(0), |
55 m_breakpointsActivated(true), | 60 m_breakpointsActivated(true), |
56 m_runningNestedMessageLoop(false), | 61 m_runningNestedMessageLoop(false), |
57 m_ignoreScriptParsedEventsCounter(0), | 62 m_ignoreScriptParsedEventsCounter(0), |
63 m_lastId(0), | |
58 m_maxAsyncCallStackDepth(0), | 64 m_maxAsyncCallStackDepth(0), |
59 m_pauseOnExceptionsState(v8::debug::NoBreakOnException), | 65 m_pauseOnExceptionsState(v8::debug::NoBreakOnException), |
60 m_wasmTranslation(isolate) {} | 66 m_wasmTranslation(isolate) {} |
61 | 67 |
62 V8Debugger::~V8Debugger() {} | 68 V8Debugger::~V8Debugger() {} |
63 | 69 |
64 void V8Debugger::enable() { | 70 void V8Debugger::enable() { |
65 if (m_enableCount++) return; | 71 if (m_enableCount++) return; |
66 DCHECK(!enabled()); | 72 DCHECK(!enabled()); |
67 v8::HandleScope scope(m_isolate); | 73 v8::HandleScope scope(m_isolate); |
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
894 int contextGroupId = | 900 int contextGroupId = |
895 m_isolate->InContext() | 901 m_isolate->InContext() |
896 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) | 902 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) |
897 : 0; | 903 : 0; |
898 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( | 904 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( |
899 this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, | 905 this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, |
900 taskName); | 906 taskName); |
901 if (chain) { | 907 if (chain) { |
902 m_asyncTaskStacks[task] = std::move(chain); | 908 m_asyncTaskStacks[task] = std::move(chain); |
903 if (recurring) m_recurringTasks.insert(task); | 909 if (recurring) m_recurringTasks.insert(task); |
910 int id = ++m_lastId; | |
911 m_rawIdToId[task] = id; | |
912 m_idToRawId[id] = task; | |
913 while (m_idToRawId.size() > kMaxAsyncTaskStacks) { | |
dgozman
2016/12/16 23:59:49
while -> if ?
kozy
2016/12/17 01:12:41
Done.
| |
914 void* taskToRemove = m_idToRawId.begin()->second; | |
915 asyncTaskCanceled(taskToRemove); | |
916 } | |
904 } | 917 } |
905 } | 918 } |
906 | 919 |
907 void V8Debugger::asyncTaskCanceled(void* task) { | 920 void V8Debugger::asyncTaskCanceled(void* task) { |
dgozman
2016/12/16 23:59:49
Note that task can be messing from any of our maps
kozy
2016/12/17 01:12:41
Done.
| |
908 if (!m_maxAsyncCallStackDepth) return; | 921 if (!m_maxAsyncCallStackDepth) return; |
909 m_asyncTaskStacks.erase(task); | 922 m_asyncTaskStacks.erase(task); |
910 m_recurringTasks.erase(task); | 923 m_recurringTasks.erase(task); |
924 auto it = m_rawIdToId.find(task); | |
925 m_idToRawId.erase(it->second); | |
926 m_rawIdToId.erase(it); | |
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 auto it = m_rawIdToId.find(task); | |
958 m_idToRawId.erase(it->second); | |
959 m_rawIdToId.erase(it); | |
960 } | |
941 } | 961 } |
942 | 962 |
943 void V8Debugger::allAsyncTasksCanceled() { | 963 void V8Debugger::allAsyncTasksCanceled() { |
944 m_asyncTaskStacks.clear(); | 964 m_asyncTaskStacks.clear(); |
945 m_recurringTasks.clear(); | 965 m_recurringTasks.clear(); |
946 m_currentStacks.clear(); | 966 m_currentStacks.clear(); |
947 m_currentTasks.clear(); | 967 m_currentTasks.clear(); |
968 m_idToRawId.clear(); | |
969 m_rawIdToId.clear(); | |
970 m_lastId = 0; | |
948 } | 971 } |
949 | 972 |
950 void V8Debugger::muteScriptParsedEvents() { | 973 void V8Debugger::muteScriptParsedEvents() { |
951 ++m_ignoreScriptParsedEventsCounter; | 974 ++m_ignoreScriptParsedEventsCounter; |
952 } | 975 } |
953 | 976 |
954 void V8Debugger::unmuteScriptParsedEvents() { | 977 void V8Debugger::unmuteScriptParsedEvents() { |
955 --m_ignoreScriptParsedEventsCounter; | 978 --m_ignoreScriptParsedEventsCounter; |
956 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); | 979 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); |
957 } | 980 } |
958 | 981 |
959 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( | 982 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
960 bool fullStack) { | 983 bool fullStack) { |
961 if (!m_isolate->InContext()) return nullptr; | 984 if (!m_isolate->InContext()) return nullptr; |
962 | 985 |
963 v8::HandleScope handles(m_isolate); | 986 v8::HandleScope handles(m_isolate); |
964 int contextGroupId = | 987 int contextGroupId = |
965 m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | 988 m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
966 if (!contextGroupId) return nullptr; | 989 if (!contextGroupId) return nullptr; |
967 | 990 |
968 size_t stackSize = | 991 size_t stackSize = |
969 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 992 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
970 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 993 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
971 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 994 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
972 | 995 |
973 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 996 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
974 } | 997 } |
975 | 998 |
976 } // namespace v8_inspector | 999 } // namespace v8_inspector |
OLD | NEW |