Chromium Code Reviews| 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 |