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" |
| (...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 void V8Debugger::asyncTaskCanceledForStack(void* task) { | 906 void V8Debugger::asyncTaskCanceledForStack(void* task) { |
| 907 if (!m_maxAsyncCallStackDepth) return; | 907 if (!m_maxAsyncCallStackDepth) return; |
| 908 m_asyncTaskStacks.erase(task); | 908 m_asyncTaskStacks.erase(task); |
| 909 m_recurringTasks.erase(task); | 909 m_recurringTasks.erase(task); |
| 910 m_parentTask.erase(task); | 910 m_parentTask.erase(task); |
| 911 m_asyncTaskCreationStacks.erase(task); | 911 m_asyncTaskCreationStacks.erase(task); |
| 912 } | 912 } |
| 913 | 913 |
| 914 void V8Debugger::asyncTaskStartedForStack(void* task) { | 914 void V8Debugger::asyncTaskStartedForStack(void* task) { |
| 915 if (!m_maxAsyncCallStackDepth) return; | 915 if (!m_maxAsyncCallStackDepth) return; |
| 916 m_currentTasks.push_back(task); | |
| 917 auto parentIt = m_parentTask.find(task); | |
| 918 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( | |
| 919 parentIt == m_parentTask.end() ? task : parentIt->second); | |
| 920 // Needs to support following order of events: | 916 // Needs to support following order of events: |
| 921 // - asyncTaskScheduled | 917 // - asyncTaskScheduled |
| 922 // <-- attached here --> | 918 // <-- attached here --> |
| 923 // - asyncTaskStarted | 919 // - asyncTaskStarted |
| 924 // - asyncTaskCanceled <-- canceled before finished | 920 // - asyncTaskCanceled <-- canceled before finished |
| 925 // <-- async stack requested here --> | 921 // <-- async stack requested here --> |
| 926 // - asyncTaskFinished | 922 // - asyncTaskFinished |
| 927 std::weak_ptr<AsyncStackTrace> asyncParent; | 923 m_currentTasks.push_back(task); |
| 928 if (stackIt != m_asyncTaskStacks.end()) asyncParent = stackIt->second; | 924 auto parentIt = m_parentTask.find(task); |
| 925 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( | |
| 926 parentIt == m_parentTask.end() ? task : parentIt->second); | |
| 927 if (stackIt != m_asyncTaskStacks.end()) { | |
| 928 m_currentAsyncParent.push_back(stackIt->second.lock()); | |
| 929 } else { | |
| 930 m_currentAsyncParent.emplace_back(); | |
| 931 } | |
| 929 auto itCreation = m_asyncTaskCreationStacks.find(task); | 932 auto itCreation = m_asyncTaskCreationStacks.find(task); |
| 930 if (asyncParent.lock() && itCreation != m_asyncTaskCreationStacks.end()) { | 933 if (itCreation != m_asyncTaskCreationStacks.end()) { |
|
kozy
2017/04/27 18:35:31
this change is essential of this CL.
| |
| 931 m_currentAsyncCreation.push_back(itCreation->second.lock()); | 934 m_currentAsyncCreation.push_back(itCreation->second.lock()); |
| 932 } else { | 935 } else { |
| 933 m_currentAsyncCreation.emplace_back(); | 936 m_currentAsyncCreation.emplace_back(); |
| 934 } | 937 } |
| 935 m_currentAsyncParent.push_back(asyncParent.lock()); | |
| 936 } | 938 } |
| 937 | 939 |
| 938 void V8Debugger::asyncTaskFinishedForStack(void* task) { | 940 void V8Debugger::asyncTaskFinishedForStack(void* task) { |
| 939 if (!m_maxAsyncCallStackDepth) return; | 941 if (!m_maxAsyncCallStackDepth) return; |
| 940 // We could start instrumenting half way and the stack is empty. | 942 // We could start instrumenting half way and the stack is empty. |
| 941 if (!m_currentTasks.size()) return; | 943 if (!m_currentTasks.size()) return; |
| 942 DCHECK(m_currentTasks.back() == task); | 944 DCHECK(m_currentTasks.back() == task); |
| 943 m_currentTasks.pop_back(); | 945 m_currentTasks.pop_back(); |
| 944 | 946 |
| 945 DCHECK(m_currentAsyncParent.size() == m_currentAsyncCreation.size()); | 947 DCHECK(m_currentAsyncParent.size() == m_currentAsyncCreation.size()); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1032 } | 1034 } |
| 1033 cleanupExpiredWeakPointers(m_asyncTaskStacks); | 1035 cleanupExpiredWeakPointers(m_asyncTaskStacks); |
| 1034 cleanupExpiredWeakPointers(m_asyncTaskCreationStacks); | 1036 cleanupExpiredWeakPointers(m_asyncTaskCreationStacks); |
| 1035 for (auto it = m_recurringTasks.begin(); it != m_recurringTasks.end();) { | 1037 for (auto it = m_recurringTasks.begin(); it != m_recurringTasks.end();) { |
| 1036 if (m_asyncTaskStacks.find(*it) == m_asyncTaskStacks.end()) { | 1038 if (m_asyncTaskStacks.find(*it) == m_asyncTaskStacks.end()) { |
| 1037 it = m_recurringTasks.erase(it); | 1039 it = m_recurringTasks.erase(it); |
| 1038 } else { | 1040 } else { |
| 1039 ++it; | 1041 ++it; |
| 1040 } | 1042 } |
| 1041 } | 1043 } |
| 1044 // We use parent information to provide correct parent stack for promises, | |
| 1045 // Promise.resolve().then(...).then(...) | |
| 1046 // created task#1 - stack#1 | |
| 1047 // scheduled task#1 - stack#2 | |
| 1048 // created task#2 -> task#1 - stack#3 | |
| 1049 // created task#3 -> task#2 - stack#4 | |
| 1050 // ... | |
| 1051 // started task#2 - use stack(parent(task#2)) == stack(task#1) == stack#2 | |
| 1052 // ... | |
| 1053 // scheduled task#2 - stack#5 | |
|
dgozman
2017/04/27 17:26:34
scheduled after started?
kozy
2017/04/27 18:35:31
yes, it's how our promise instrumentation works an
| |
| 1054 // finished task#2 | |
| 1055 // started task#3 - use stack(parent(task#3)) == stack(task#2) == stack#5 | |
| 1056 // ... | |
| 1057 // scheduled task#3 - stack#6 | |
| 1058 // finished task#3 | |
| 1059 // Let's consider what parent link is obsolete when we collect stacks: | |
| 1060 // stack#1 - (task#2 -> task#1, task#3 -> task#2) | |
| 1061 // stack#2 - (task#3 -> task#2) | |
| 1062 // stack#3 - (task#3 -> task#2) | |
| 1063 // stack#4 - (task#3 -> task#2) | |
| 1064 // stack#5 - () | |
| 1065 // stack#6 - () | |
| 1066 // But in case when we start collecting stacks after getting stack#4 but | |
| 1067 // before stack#5 is added we should preserve parent link since original task | |
| 1068 // can be scheduled at any time in future and this link will be required to | |
| 1069 // get correct parent stack later. It means that we should collect parent link | |
| 1070 // in case when there is no creation or schedule stack for parent. | |
| 1042 for (auto it = m_parentTask.begin(); it != m_parentTask.end();) { | 1071 for (auto it = m_parentTask.begin(); it != m_parentTask.end();) { |
| 1043 if (m_asyncTaskCreationStacks.find(it->second) == | 1072 if (m_asyncTaskCreationStacks.find(it->second) == |
| 1044 m_asyncTaskCreationStacks.end()) { | 1073 m_asyncTaskCreationStacks.end() && |
| 1074 m_asyncTaskStacks.find(it->second) == m_asyncTaskStacks.end()) { | |
| 1045 it = m_parentTask.erase(it); | 1075 it = m_parentTask.erase(it); |
| 1046 } else { | 1076 } else { |
| 1047 ++it; | 1077 ++it; |
| 1048 } | 1078 } |
| 1049 } | 1079 } |
| 1050 cleanupExpiredWeakPointers(m_framesCache); | 1080 cleanupExpiredWeakPointers(m_framesCache); |
| 1051 } | 1081 } |
| 1052 | 1082 |
| 1053 std::shared_ptr<StackFrame> V8Debugger::symbolize( | 1083 std::shared_ptr<StackFrame> V8Debugger::symbolize( |
| 1054 v8::Local<v8::StackFrame> v8Frame) { | 1084 v8::Local<v8::StackFrame> v8Frame) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1079 fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount); | 1109 fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount); |
| 1080 fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size()); | 1110 fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size()); |
| 1081 fprintf(stdout, "Created async tasks: %zu\n", | 1111 fprintf(stdout, "Created async tasks: %zu\n", |
| 1082 m_asyncTaskCreationStacks.size()); | 1112 m_asyncTaskCreationStacks.size()); |
| 1083 fprintf(stdout, "Async tasks with parent: %zu\n", m_parentTask.size()); | 1113 fprintf(stdout, "Async tasks with parent: %zu\n", m_parentTask.size()); |
| 1084 fprintf(stdout, "Recurring async tasks: %zu\n", m_recurringTasks.size()); | 1114 fprintf(stdout, "Recurring async tasks: %zu\n", m_recurringTasks.size()); |
| 1085 fprintf(stdout, "\n"); | 1115 fprintf(stdout, "\n"); |
| 1086 } | 1116 } |
| 1087 | 1117 |
| 1088 } // namespace v8_inspector | 1118 } // namespace v8_inspector |
| OLD | NEW |