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 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 m_pauseOnExceptionsState = pauseOnExceptionsState; | 328 m_pauseOnExceptionsState = pauseOnExceptionsState; |
| 329 } | 329 } |
| 330 | 330 |
| 331 void V8Debugger::setPauseOnNextStatement(bool pause, int targetContextGroupId) { | 331 void V8Debugger::setPauseOnNextStatement(bool pause, int targetContextGroupId) { |
| 332 if (isPaused()) return; | 332 if (isPaused()) return; |
| 333 DCHECK(targetContextGroupId); | 333 DCHECK(targetContextGroupId); |
| 334 if (!pause && m_targetContextGroupId && | 334 if (!pause && m_targetContextGroupId && |
| 335 m_targetContextGroupId != targetContextGroupId) { | 335 m_targetContextGroupId != targetContextGroupId) { |
| 336 return; | 336 return; |
| 337 } | 337 } |
| 338 DCHECK(m_targetContextGroupId == targetContextGroupId || | |
| 339 !m_targetContextGroupId); | |
| 338 m_targetContextGroupId = targetContextGroupId; | 340 m_targetContextGroupId = targetContextGroupId; |
| 341 m_breakRequested = pause; | |
| 339 if (pause) | 342 if (pause) |
| 340 v8::debug::DebugBreak(m_isolate); | 343 v8::debug::DebugBreak(m_isolate); |
| 341 else | 344 else |
| 342 v8::debug::CancelDebugBreak(m_isolate); | 345 v8::debug::CancelDebugBreak(m_isolate); |
| 343 } | 346 } |
| 344 | 347 |
| 345 bool V8Debugger::canBreakProgram() { | 348 bool V8Debugger::canBreakProgram() { |
| 346 if (!m_breakpointsActivated) return false; | 349 if (!m_breakpointsActivated) return false; |
| 347 return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate); | 350 return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate); |
| 348 } | 351 } |
| 349 | 352 |
| 350 void V8Debugger::breakProgram() { | 353 void V8Debugger::breakProgram() { |
| 351 // Don't allow nested breaks. | 354 // Don't allow nested breaks. |
| 352 if (isPaused()) return; | 355 if (isPaused()) return; |
| 353 if (!canBreakProgram()) return; | 356 if (!canBreakProgram()) return; |
| 354 v8::debug::BreakRightNow(m_isolate); | 357 v8::debug::BreakRightNow(m_isolate); |
| 355 } | 358 } |
| 356 | 359 |
| 357 void V8Debugger::continueProgram() { | 360 void V8Debugger::continueProgram() { |
| 358 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); | 361 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); |
| 359 m_pausedContext.Clear(); | 362 m_pausedContext.Clear(); |
| 360 m_executionState.Clear(); | 363 m_executionState.Clear(); |
| 361 } | 364 } |
| 362 | 365 |
| 363 void V8Debugger::stepIntoStatement(int targetContextGroupId) { | 366 void V8Debugger::stepIntoStatement(int targetContextGroupId) { |
| 364 DCHECK(isPaused()); | 367 DCHECK(isPaused()); |
| 365 DCHECK(!m_executionState.IsEmpty()); | 368 DCHECK(!m_executionState.IsEmpty()); |
| 366 DCHECK(targetContextGroupId); | 369 DCHECK(targetContextGroupId); |
| 370 DCHECK(m_targetContextGroupId == targetContextGroupId || | |
| 371 !m_targetContextGroupId); | |
|
dgozman
2017/03/28 23:20:50
Merge with previous DCHECK and simplify it :-)
kozy
2017/03/28 23:49:49
this dcheck is redundant so removed.
| |
| 367 m_targetContextGroupId = targetContextGroupId; | 372 m_targetContextGroupId = targetContextGroupId; |
| 368 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); | 373 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); |
| 369 continueProgram(); | 374 continueProgram(); |
| 370 } | 375 } |
| 371 | 376 |
| 372 void V8Debugger::stepOverStatement(int targetContextGroupId) { | 377 void V8Debugger::stepOverStatement(int targetContextGroupId) { |
| 373 DCHECK(isPaused()); | 378 DCHECK(isPaused()); |
| 374 DCHECK(!m_executionState.IsEmpty()); | 379 DCHECK(!m_executionState.IsEmpty()); |
| 375 DCHECK(targetContextGroupId); | 380 DCHECK(targetContextGroupId); |
| 381 DCHECK(m_targetContextGroupId == targetContextGroupId || | |
|
dgozman
2017/03/28 23:20:50
everywhere
kozy
2017/03/28 23:49:49
Done.
| |
| 382 !m_targetContextGroupId); | |
| 376 m_targetContextGroupId = targetContextGroupId; | 383 m_targetContextGroupId = targetContextGroupId; |
| 377 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); | 384 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); |
| 378 continueProgram(); | 385 continueProgram(); |
| 379 } | 386 } |
| 380 | 387 |
| 381 void V8Debugger::stepOutOfFunction(int targetContextGroupId) { | 388 void V8Debugger::stepOutOfFunction(int targetContextGroupId) { |
| 382 DCHECK(isPaused()); | 389 DCHECK(isPaused()); |
| 383 DCHECK(!m_executionState.IsEmpty()); | 390 DCHECK(!m_executionState.IsEmpty()); |
| 384 DCHECK(targetContextGroupId); | 391 DCHECK(targetContextGroupId); |
| 392 DCHECK(m_targetContextGroupId == targetContextGroupId || | |
| 393 !m_targetContextGroupId); | |
| 385 m_targetContextGroupId = targetContextGroupId; | 394 m_targetContextGroupId = targetContextGroupId; |
| 386 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); | 395 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); |
| 387 continueProgram(); | 396 continueProgram(); |
| 388 } | 397 } |
| 389 | 398 |
| 399 void V8Debugger::scheduleStepIntoAsync( | |
| 400 std::unique_ptr<ScheduleStepIntoAsyncCallback> callback, | |
| 401 int targetContextGroupId) { | |
| 402 DCHECK(isPaused()); | |
| 403 DCHECK(!m_executionState.IsEmpty()); | |
| 404 DCHECK(targetContextGroupId); | |
| 405 if (m_stepIntoAsyncCallback) { | |
| 406 m_stepIntoAsyncCallback->sendFailure(Response::Error( | |
| 407 "Current scheduled step into async was overriden with new one.")); | |
| 408 } | |
| 409 m_targetContextGroupId = targetContextGroupId; | |
| 410 m_stepIntoAsyncCallback = std::move(callback); | |
| 411 } | |
| 412 | |
| 390 Response V8Debugger::setScriptSource( | 413 Response V8Debugger::setScriptSource( |
| 391 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, | 414 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, |
| 392 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, | 415 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, |
| 393 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, | 416 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, |
| 394 bool* compileError) { | 417 bool* compileError) { |
| 395 class EnableLiveEditScope { | 418 class EnableLiveEditScope { |
| 396 public: | 419 public: |
| 397 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { | 420 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { |
| 398 v8::debug::SetLiveEditEnabled(m_isolate, true); | 421 v8::debug::SetLiveEditEnabled(m_isolate, true); |
| 399 inLiveEditScope = true; | 422 inLiveEditScope = true; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 bool isPromiseRejection, bool isUncaught) { | 538 bool isPromiseRejection, bool isUncaught) { |
| 516 // Don't allow nested breaks. | 539 // Don't allow nested breaks. |
| 517 if (isPaused()) return; | 540 if (isPaused()) return; |
| 518 | 541 |
| 519 int contextGroupId = m_inspector->contextGroupId(pausedContext); | 542 int contextGroupId = m_inspector->contextGroupId(pausedContext); |
| 520 if (m_targetContextGroupId && contextGroupId != m_targetContextGroupId) { | 543 if (m_targetContextGroupId && contextGroupId != m_targetContextGroupId) { |
| 521 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); | 544 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); |
| 522 return; | 545 return; |
| 523 } | 546 } |
| 524 m_targetContextGroupId = 0; | 547 m_targetContextGroupId = 0; |
| 548 if (m_stepIntoAsyncCallback) { | |
| 549 m_stepIntoAsyncCallback->sendFailure( | |
| 550 Response::Error("No async tasks were scheduled before pause.")); | |
| 551 m_stepIntoAsyncCallback.reset(); | |
| 552 } | |
| 525 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( | 553 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( |
| 526 m_inspector->contextGroupId(pausedContext)); | 554 m_inspector->contextGroupId(pausedContext)); |
| 527 if (!agent || (agent->skipAllPauses() && !m_scheduledOOMBreak)) return; | 555 if (!agent || (agent->skipAllPauses() && !m_scheduledOOMBreak)) return; |
| 528 | 556 |
| 529 std::vector<String16> breakpointIds; | 557 std::vector<String16> breakpointIds; |
| 530 if (!hitBreakpointNumbers.IsEmpty()) { | 558 if (!hitBreakpointNumbers.IsEmpty()) { |
| 531 breakpointIds.reserve(hitBreakpointNumbers->Length()); | 559 breakpointIds.reserve(hitBreakpointNumbers->Length()); |
| 532 for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { | 560 for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { |
| 533 v8::Local<v8::Value> hitBreakpointNumber = | 561 v8::Local<v8::Value> hitBreakpointNumber = |
| 534 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); | 562 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 // Async task events from Promises are given misaligned pointers to prevent | 654 // Async task events from Promises are given misaligned pointers to prevent |
| 627 // from overlapping with other Blink task identifiers. There is a single | 655 // from overlapping with other Blink task identifiers. There is a single |
| 628 // namespace of such ids, managed by src/js/promise.js. | 656 // namespace of such ids, managed by src/js/promise.js. |
| 629 void* ptr = reinterpret_cast<void*>(id * 2 + 1); | 657 void* ptr = reinterpret_cast<void*>(id * 2 + 1); |
| 630 void* parentPtr = | 658 void* parentPtr = |
| 631 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; | 659 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; |
| 632 handleAsyncTaskStepping(context, type, ptr, parentPtr, createdByUser); | 660 handleAsyncTaskStepping(context, type, ptr, parentPtr, createdByUser); |
| 633 if (!m_maxAsyncCallStackDepth) return; | 661 if (!m_maxAsyncCallStackDepth) return; |
| 634 switch (type) { | 662 switch (type) { |
| 635 case v8::debug::kDebugPromiseCreated: | 663 case v8::debug::kDebugPromiseCreated: |
| 636 asyncTaskCreated(ptr, parentPtr); | 664 asyncTaskCreatedForStack(ptr, parentPtr); |
| 637 break; | 665 break; |
| 638 case v8::debug::kDebugEnqueueAsyncFunction: | 666 case v8::debug::kDebugEnqueueAsyncFunction: |
| 639 asyncTaskScheduled("async function", ptr, true); | 667 asyncTaskScheduledForStack("async function", ptr, true); |
| 640 break; | 668 break; |
| 641 case v8::debug::kDebugEnqueuePromiseResolve: | 669 case v8::debug::kDebugEnqueuePromiseResolve: |
| 642 asyncTaskScheduled("Promise.resolve", ptr, true); | 670 asyncTaskScheduledForStack("Promise.resolve", ptr, true); |
| 643 break; | 671 break; |
| 644 case v8::debug::kDebugEnqueuePromiseReject: | 672 case v8::debug::kDebugEnqueuePromiseReject: |
| 645 asyncTaskScheduled("Promise.reject", ptr, true); | 673 asyncTaskScheduledForStack("Promise.reject", ptr, true); |
| 646 break; | 674 break; |
| 647 case v8::debug::kDebugPromiseCollected: | 675 case v8::debug::kDebugPromiseCollected: |
| 648 asyncTaskCanceled(ptr); | 676 asyncTaskCanceledForStack(ptr); |
| 649 break; | 677 break; |
| 650 case v8::debug::kDebugWillHandle: | 678 case v8::debug::kDebugWillHandle: |
| 651 asyncTaskStarted(ptr); | 679 asyncTaskStartedForStack(ptr); |
| 652 break; | 680 break; |
| 653 case v8::debug::kDebugDidHandle: | 681 case v8::debug::kDebugDidHandle: |
| 654 asyncTaskFinished(ptr); | 682 asyncTaskFinishedForStack(ptr); |
| 655 break; | 683 break; |
| 656 } | 684 } |
| 657 } | 685 } |
| 658 | 686 |
| 659 void V8Debugger::handleAsyncTaskStepping(v8::Local<v8::Context> context, | 687 void V8Debugger::handleAsyncTaskStepping(v8::Local<v8::Context> context, |
|
dgozman
2017/03/28 23:20:50
handlePromiseAsyncStepping
kozy
2017/03/28 23:49:50
removed this method.
| |
| 660 v8::debug::PromiseDebugActionType type, | 688 v8::debug::PromiseDebugActionType type, |
| 661 void* task, void* parentTask, | 689 void* task, void* parentTask, |
| 662 bool createdByUser) { | 690 bool createdByUser) { |
| 663 if (type == v8::debug::kDebugEnqueueAsyncFunction || | 691 if (type == v8::debug::kDebugEnqueueAsyncFunction || |
| 664 type == v8::debug::kDebugEnqueuePromiseResolve || | 692 type == v8::debug::kDebugEnqueuePromiseResolve || |
| 665 type == v8::debug::kDebugEnqueuePromiseReject) { | 693 type == v8::debug::kDebugEnqueuePromiseReject) { |
| 666 return; | 694 return; |
| 667 } | 695 } |
| 668 | 696 |
| 669 bool isScheduledTask = task == m_taskWithScheduledBreak; | 697 bool isScheduledTask = task == m_taskWithScheduledBreak; |
| 670 if (type == v8::debug::kDebugPromiseCollected) { | 698 if (type == v8::debug::kDebugPromiseCollected) { |
| 671 if (isScheduledTask) m_taskWithScheduledBreak = nullptr; | 699 if (isScheduledTask) m_taskWithScheduledBreak = nullptr; |
| 672 return; | 700 return; |
| 673 } | 701 } |
| 674 if (type == v8::debug::kDebugPromiseCreated && !parentTask) return; | 702 if (type == v8::debug::kDebugPromiseCreated && !parentTask) return; |
| 675 | 703 |
| 676 DCHECK(!context.IsEmpty()); | 704 DCHECK(!context.IsEmpty()); |
| 677 int contextGroupId = m_inspector->contextGroupId(context); | 705 int contextGroupId = m_inspector->contextGroupId(context); |
| 678 V8DebuggerAgentImpl* agent = | 706 V8DebuggerAgentImpl* agent = |
| 679 m_inspector->enabledDebuggerAgentForGroup(contextGroupId); | 707 m_inspector->enabledDebuggerAgentForGroup(contextGroupId); |
| 680 if (!agent) return; | 708 if (!agent) return; |
| 681 if (createdByUser && type == v8::debug::kDebugPromiseCreated) { | 709 if (createdByUser && type == v8::debug::kDebugPromiseCreated) { |
| 682 if (agent->shouldBreakInScheduledAsyncTask()) { | 710 if (contextGroupId == m_targetContextGroupId && m_stepIntoAsyncCallback) { |
| 683 m_taskWithScheduledBreak = task; | 711 m_taskWithScheduledBreak = task; |
| 684 v8::debug::ClearStepping(m_isolate); | 712 v8::debug::ClearStepping(m_isolate); |
| 713 m_stepIntoAsyncCallback->sendSuccess(); | |
| 714 m_stepIntoAsyncCallback.reset(); | |
| 685 } | 715 } |
| 686 return; | 716 return; |
| 687 } | 717 } |
| 688 if (!isScheduledTask) return; | 718 if (!isScheduledTask) return; |
| 689 if (type == v8::debug::kDebugWillHandle) { | 719 if (type == v8::debug::kDebugWillHandle) { |
| 690 agent->schedulePauseOnNextStatement( | 720 if (!m_breakRequested) v8::debug::DebugBreak(m_isolate); |
| 691 protocol::Debugger::Paused::ReasonEnum::Other, nullptr); | |
| 692 return; | 721 return; |
| 693 } | 722 } |
| 694 DCHECK(type == v8::debug::kDebugDidHandle); | 723 DCHECK(type == v8::debug::kDebugDidHandle); |
| 695 agent->cancelPauseOnNextStatement(); | 724 if (!m_breakRequested) v8::debug::CancelDebugBreak(m_isolate); |
| 696 m_taskWithScheduledBreak = nullptr; | 725 m_taskWithScheduledBreak = nullptr; |
| 697 } | 726 } |
| 698 | 727 |
| 699 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { | 728 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { |
| 700 if (!m_currentStacks.size()) return nullptr; | 729 if (!m_currentStacks.size()) return nullptr; |
| 701 return m_currentStacks.back().get(); | 730 return m_currentStacks.back().get(); |
| 702 } | 731 } |
| 703 | 732 |
| 704 void V8Debugger::compileDebuggerScript() { | 733 void V8Debugger::compileDebuggerScript() { |
| 705 if (!m_debuggerScript.IsEmpty()) { | 734 if (!m_debuggerScript.IsEmpty()) { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 862 } | 891 } |
| 863 | 892 |
| 864 void V8Debugger::registerAsyncTaskIfNeeded(void* task) { | 893 void V8Debugger::registerAsyncTaskIfNeeded(void* task) { |
| 865 if (m_taskToId.find(task) != m_taskToId.end()) return; | 894 if (m_taskToId.find(task) != m_taskToId.end()) return; |
| 866 | 895 |
| 867 int id = ++m_lastTaskId; | 896 int id = ++m_lastTaskId; |
| 868 m_taskToId[task] = id; | 897 m_taskToId[task] = id; |
| 869 m_idToTask[id] = task; | 898 m_idToTask[id] = task; |
| 870 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) { | 899 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) { |
| 871 void* taskToRemove = m_idToTask.begin()->second; | 900 void* taskToRemove = m_idToTask.begin()->second; |
| 872 asyncTaskCanceled(taskToRemove); | 901 asyncTaskCanceledForStack(taskToRemove); |
| 873 } | 902 } |
| 874 } | 903 } |
| 875 | 904 |
| 876 void V8Debugger::asyncTaskCreated(void* task, void* parentTask) { | 905 void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) { |
| 877 if (!m_maxAsyncCallStackDepth) return; | 906 if (!m_maxAsyncCallStackDepth) return; |
| 878 if (parentTask) m_parentTask[task] = parentTask; | 907 if (parentTask) m_parentTask[task] = parentTask; |
| 879 v8::HandleScope scope(m_isolate); | 908 v8::HandleScope scope(m_isolate); |
| 880 // We don't need to pass context group id here because we get this callback | 909 // We don't need to pass context group id here because we get this callback |
| 881 // from V8 for promise events only. | 910 // from V8 for promise events only. |
| 882 // Passing one as maxStackSize forces no async chain for the new stack and | 911 // Passing one as maxStackSize forces no async chain for the new stack and |
| 883 // allows us to not grow exponentially. | 912 // allows us to not grow exponentially. |
| 884 std::unique_ptr<V8StackTraceImpl> creationStack = | 913 std::unique_ptr<V8StackTraceImpl> creationStack = |
| 885 V8StackTraceImpl::capture(this, 0, 1, String16()); | 914 V8StackTraceImpl::capture(this, 0, 1, String16()); |
| 886 if (creationStack && !creationStack->isEmpty()) { | 915 if (creationStack && !creationStack->isEmpty()) { |
| 887 m_asyncTaskCreationStacks[task] = std::move(creationStack); | 916 m_asyncTaskCreationStacks[task] = std::move(creationStack); |
| 888 registerAsyncTaskIfNeeded(task); | 917 registerAsyncTaskIfNeeded(task); |
| 889 } | 918 } |
| 890 } | 919 } |
| 891 | 920 |
| 892 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, | 921 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
| 893 bool recurring) { | 922 bool recurring) { |
| 894 if (!m_maxAsyncCallStackDepth) return; | 923 asyncTaskScheduledForStack(toString16(taskName), task, recurring); |
| 895 asyncTaskScheduled(toString16(taskName), task, recurring); | 924 if (currentContextGroupId() == m_targetContextGroupId && |
| 925 m_stepIntoAsyncCallback) { | |
| 926 m_taskWithScheduledBreak = task; | |
| 927 v8::debug::ClearStepping(m_isolate); | |
| 928 m_stepIntoAsyncCallback->sendSuccess(); | |
| 929 m_stepIntoAsyncCallback.reset(); | |
| 930 } | |
| 896 } | 931 } |
| 897 | 932 |
| 898 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, | 933 void V8Debugger::asyncTaskCanceled(void* task) { |
| 899 bool recurring) { | 934 asyncTaskCanceledForStack(task); |
| 935 if (task == m_taskWithScheduledBreak) { | |
| 936 m_taskWithScheduledBreak = nullptr; | |
| 937 } | |
| 938 } | |
| 939 | |
| 940 void V8Debugger::asyncTaskStarted(void* task) { | |
| 941 asyncTaskStartedForStack(task); | |
| 942 if (task == m_taskWithScheduledBreak) { | |
| 943 if (!m_breakRequested) v8::debug::DebugBreak(m_isolate); | |
| 944 } | |
| 945 } | |
| 946 | |
| 947 void V8Debugger::asyncTaskFinished(void* task) { | |
| 948 asyncTaskFinishedForStack(task); | |
| 949 if (task == m_taskWithScheduledBreak) { | |
| 950 if (!m_breakRequested) v8::debug::CancelDebugBreak(m_isolate); | |
| 951 } | |
| 952 } | |
| 953 | |
| 954 void V8Debugger::asyncTaskScheduledForStack(const String16& taskName, | |
| 955 void* task, bool recurring) { | |
| 900 if (!m_maxAsyncCallStackDepth) return; | 956 if (!m_maxAsyncCallStackDepth) return; |
| 901 v8::HandleScope scope(m_isolate); | 957 v8::HandleScope scope(m_isolate); |
| 902 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( | 958 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( |
| 903 this, currentContextGroupId(), | 959 this, currentContextGroupId(), |
| 904 V8StackTraceImpl::maxCallStackSizeToCapture, taskName); | 960 V8StackTraceImpl::maxCallStackSizeToCapture, taskName); |
| 905 if (chain) { | 961 if (chain) { |
| 906 m_asyncTaskStacks[task] = std::move(chain); | 962 m_asyncTaskStacks[task] = std::move(chain); |
| 907 if (recurring) m_recurringTasks.insert(task); | 963 if (recurring) m_recurringTasks.insert(task); |
| 908 registerAsyncTaskIfNeeded(task); | 964 registerAsyncTaskIfNeeded(task); |
| 909 } | 965 } |
| 910 } | 966 } |
| 911 | 967 |
| 912 void V8Debugger::asyncTaskCanceled(void* task) { | 968 void V8Debugger::asyncTaskCanceledForStack(void* task) { |
| 913 if (!m_maxAsyncCallStackDepth) return; | 969 if (!m_maxAsyncCallStackDepth) return; |
| 914 m_asyncTaskStacks.erase(task); | 970 m_asyncTaskStacks.erase(task); |
| 915 m_recurringTasks.erase(task); | 971 m_recurringTasks.erase(task); |
| 916 m_parentTask.erase(task); | 972 m_parentTask.erase(task); |
| 917 m_asyncTaskCreationStacks.erase(task); | 973 m_asyncTaskCreationStacks.erase(task); |
| 918 auto it = m_taskToId.find(task); | 974 auto it = m_taskToId.find(task); |
| 919 if (it == m_taskToId.end()) return; | 975 if (it == m_taskToId.end()) return; |
| 920 m_idToTask.erase(it->second); | 976 m_idToTask.erase(it->second); |
| 921 m_taskToId.erase(it); | 977 m_taskToId.erase(it); |
| 922 } | 978 } |
| 923 | 979 |
| 924 void V8Debugger::asyncTaskStarted(void* task) { | 980 void V8Debugger::asyncTaskStartedForStack(void* task) { |
| 925 if (!m_maxAsyncCallStackDepth) return; | 981 if (!m_maxAsyncCallStackDepth) return; |
| 926 m_currentTasks.push_back(task); | 982 m_currentTasks.push_back(task); |
| 927 auto parentIt = m_parentTask.find(task); | 983 auto parentIt = m_parentTask.find(task); |
| 928 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( | 984 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( |
| 929 parentIt == m_parentTask.end() ? task : parentIt->second); | 985 parentIt == m_parentTask.end() ? task : parentIt->second); |
| 930 // Needs to support following order of events: | 986 // Needs to support following order of events: |
| 931 // - asyncTaskScheduled | 987 // - asyncTaskScheduled |
| 932 // <-- attached here --> | 988 // <-- attached here --> |
| 933 // - asyncTaskStarted | 989 // - asyncTaskStarted |
| 934 // - asyncTaskCanceled <-- canceled before finished | 990 // - asyncTaskCanceled <-- canceled before finished |
| 935 // <-- async stack requested here --> | 991 // <-- async stack requested here --> |
| 936 // - asyncTaskFinished | 992 // - asyncTaskFinished |
| 937 std::unique_ptr<V8StackTraceImpl> stack; | 993 std::unique_ptr<V8StackTraceImpl> stack; |
| 938 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) | 994 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) |
| 939 stack = stackIt->second->cloneImpl(); | 995 stack = stackIt->second->cloneImpl(); |
| 940 auto itCreation = m_asyncTaskCreationStacks.find(task); | 996 auto itCreation = m_asyncTaskCreationStacks.find(task); |
| 941 if (stack && itCreation != m_asyncTaskCreationStacks.end()) { | 997 if (stack && itCreation != m_asyncTaskCreationStacks.end()) { |
| 942 stack->setCreation(itCreation->second->cloneImpl()); | 998 stack->setCreation(itCreation->second->cloneImpl()); |
| 943 } | 999 } |
| 944 m_currentStacks.push_back(std::move(stack)); | 1000 m_currentStacks.push_back(std::move(stack)); |
| 945 } | 1001 } |
| 946 | 1002 |
| 947 void V8Debugger::asyncTaskFinished(void* task) { | 1003 void V8Debugger::asyncTaskFinishedForStack(void* task) { |
| 948 if (!m_maxAsyncCallStackDepth) return; | 1004 if (!m_maxAsyncCallStackDepth) return; |
| 949 // We could start instrumenting half way and the stack is empty. | 1005 // We could start instrumenting half way and the stack is empty. |
| 950 if (!m_currentStacks.size()) return; | 1006 if (!m_currentStacks.size()) return; |
| 951 | 1007 |
| 952 DCHECK(m_currentTasks.back() == task); | 1008 DCHECK(m_currentTasks.back() == task); |
| 953 m_currentTasks.pop_back(); | 1009 m_currentTasks.pop_back(); |
| 954 | 1010 |
| 955 m_currentStacks.pop_back(); | 1011 m_currentStacks.pop_back(); |
| 956 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { | 1012 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { |
| 957 asyncTaskCanceled(task); | 1013 asyncTaskCanceledForStack(task); |
| 958 } | 1014 } |
| 959 } | 1015 } |
| 960 | 1016 |
| 961 void V8Debugger::allAsyncTasksCanceled() { | 1017 void V8Debugger::allAsyncTasksCanceled() { |
| 962 m_asyncTaskStacks.clear(); | 1018 m_asyncTaskStacks.clear(); |
| 963 m_recurringTasks.clear(); | 1019 m_recurringTasks.clear(); |
| 964 m_currentStacks.clear(); | 1020 m_currentStacks.clear(); |
| 965 m_currentTasks.clear(); | 1021 m_currentTasks.clear(); |
| 966 m_parentTask.clear(); | 1022 m_parentTask.clear(); |
| 967 m_asyncTaskCreationStacks.clear(); | 1023 m_asyncTaskCreationStacks.clear(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 994 | 1050 |
| 995 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1051 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
| 996 } | 1052 } |
| 997 | 1053 |
| 998 int V8Debugger::currentContextGroupId() { | 1054 int V8Debugger::currentContextGroupId() { |
| 999 if (!m_isolate->InContext()) return 0; | 1055 if (!m_isolate->InContext()) return 0; |
| 1000 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | 1056 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
| 1001 } | 1057 } |
| 1002 | 1058 |
| 1003 } // namespace v8_inspector | 1059 } // namespace v8_inspector |
| OLD | NEW |