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 | 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |