Commit 6d87d957 authored by Alexey Kozyatinskiy's avatar Alexey Kozyatinskiy Committed by Commit Bot

[inspector] use interrupt for pause only as last resort

With this CL we use interrupt for pause in two cases:
- when we process Debugger.pause on interruption,
- when we would like to break as soon as possible after OOM.
In all other cases, e.g. for async step into we use break
on function call by calling StepIn debugger action.

In mentioned cases we should not actually use interrupt as well:
- Debugger.pause in this case scheduled using interrupt and we
  may just break right now without requesting another interrupt,
  unfortunately blink side is not ready,
- we should use more reliable way to break right after near OOM
  callback, otherwise we can get this callback, increase limit,
  request break on next interrupt, before interrupt get another
  huge memory allocation and crash.

There are couple advantages:
- we get much better break locations for async stepping
  (see inspector tests expectations),
- we can remove DEBUG_BREAK interruption
  (it should speedup blackboxing with async tasks, see
  removed todo in debug.cc for details)
- it is required preparation step for async step out,
  (see https://chromium-review.googlesource.com/c/v8/v8/+/1054618)

Bug: v8:7753
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Iabd7627dbffa9a0eab1736064caf589d02591926
Reviewed-on: https://chromium-review.googlesource.com/1054155
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53439}
parent f3131cef
......@@ -9135,13 +9135,14 @@ void debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
internal_isolate->debug()->set_live_edit_enabled(enable);
}
void debug::DebugBreak(Isolate* isolate) {
reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
void debug::SetBreakOnNextFunctionCall(Isolate* isolate) {
reinterpret_cast<i::Isolate*>(isolate)->debug()->SetBreakOnNextFunctionCall();
}
void debug::CancelDebugBreak(Isolate* isolate) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
internal_isolate->stack_guard()->ClearDebugBreak();
void debug::ClearBreakOnNextFunctionCall(Isolate* isolate) {
reinterpret_cast<i::Isolate*>(isolate)
->debug()
->ClearBreakOnNextFunctionCall();
}
MaybeLocal<Array> debug::GetInternalProperties(Isolate* v8_isolate,
......@@ -9169,11 +9170,6 @@ void debug::SetBreakPointsActive(Isolate* v8_isolate, bool is_active) {
isolate->debug()->set_break_points_active(is_active);
}
void debug::SetOutOfMemoryCallback(Isolate* isolate,
OutOfMemoryCallback callback, void* data) {
// No-op.
}
void debug::PrepareStep(Isolate* v8_isolate, StepAction action) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
ENTER_V8_DO_NOT_USE(isolate);
......
......@@ -71,13 +71,13 @@ MaybeLocal<Value> Call(Local<Context> context, v8::Local<v8::Function> fun,
*/
V8_EXPORT_PRIVATE void SetLiveEditEnabled(Isolate* isolate, bool enable);
// Schedule a debugger break to happen when JavaScript code is run
// in the given isolate.
void DebugBreak(Isolate* isolate);
// Schedule a debugger break to happen when function is called inside given
// isolate.
void SetBreakOnNextFunctionCall(Isolate* isolate);
// Remove scheduled debugger break in given isolate if it has not
// happened yet.
void CancelDebugBreak(Isolate* isolate);
void ClearBreakOnNextFunctionCall(Isolate* isolate);
/**
* Returns array of internal properties specific to the value type. Result has
......@@ -116,19 +116,6 @@ void BreakRightNow(Isolate* isolate);
bool AllFramesOnStackAreBlackboxed(Isolate* isolate);
/**
* Out-of-memory callback function.
* The function is invoked when the heap size is close to the hard limit.
*
* \param data the parameter provided during callback installation.
*/
typedef void (*OutOfMemoryCallback)(void* data);
V8_DEPRECATED("Use v8::Isolate::AddNearHeapLimitCallback",
void SetOutOfMemoryCallback(Isolate* isolate,
OutOfMemoryCallback callback,
void* data));
/**
* Native wrapper around v8::internal::Script object.
*/
......
......@@ -351,6 +351,7 @@ void Debug::ThreadInit() {
thread_local_.restart_fp_ = kNullAddress;
base::Relaxed_Store(&thread_local_.current_debug_scope_,
static_cast<base::AtomicWord>(0));
thread_local_.break_on_next_function_call_ = false;
UpdateHookOnFunctionCall();
}
......@@ -474,11 +475,13 @@ void Debug::Break(JavaScriptFrame* frame, Handle<JSFunction> break_target) {
// Find actual break points, if any, and trigger debug break event.
MaybeHandle<FixedArray> break_points_hit =
CheckBreakPoints(debug_info, &location);
if (!break_points_hit.is_null()) {
if (!break_points_hit.is_null() || break_on_next_function_call()) {
// Clear all current stepping setup.
ClearStepping();
// Notify the debug event listeners.
OnDebugBreak(break_points_hit.ToHandleChecked());
OnDebugBreak(!break_points_hit.is_null()
? break_points_hit.ToHandleChecked()
: isolate_->factory()->empty_fixed_array());
return;
}
......@@ -898,8 +901,24 @@ MaybeHandle<FixedArray> Debug::GetHitBreakPoints(Handle<DebugInfo> debug_info,
return break_points_hit;
}
void Debug::SetBreakOnNextFunctionCall() {
// This method forces V8 to break on next function call regardless current
// last_step_action_. If any break happens between SetBreakOnNextFunctionCall
// and ClearBreakOnNextFunctionCall, we will clear this flag and stepping. If
// break does not happen, e.g. all called functions are blackboxed or no
// function is called, then we will clear this flag and let stepping continue
// its normal business.
thread_local_.break_on_next_function_call_ = true;
UpdateHookOnFunctionCall();
}
void Debug::ClearBreakOnNextFunctionCall() {
thread_local_.break_on_next_function_call_ = false;
UpdateHookOnFunctionCall();
}
void Debug::PrepareStepIn(Handle<JSFunction> function) {
CHECK(last_step_action() >= StepIn);
CHECK(last_step_action() >= StepIn || break_on_next_function_call());
if (ignore_events()) return;
if (in_debug_scope()) return;
if (break_disabled()) return;
......@@ -1159,6 +1178,7 @@ void Debug::ClearStepping() {
thread_local_.fast_forward_to_return_ = false;
thread_local_.last_frame_count_ = -1;
thread_local_.target_frame_count_ = -1;
thread_local_.break_on_next_function_call_ = false;
UpdateHookOnFunctionCall();
}
......@@ -2157,7 +2177,8 @@ void Debug::UpdateHookOnFunctionCall() {
STATIC_ASSERT(LastStepAction == StepIn);
hook_on_function_call_ =
thread_local_.last_step_action_ == StepIn ||
isolate_->debug_execution_mode() == DebugInfo::kSideEffects;
isolate_->debug_execution_mode() == DebugInfo::kSideEffects ||
thread_local_.break_on_next_function_call_;
}
MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
......@@ -2204,19 +2225,7 @@ void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode) {
bool ignore_break = ignore_break_mode == kIgnoreIfTopFrameBlackboxed
? IsBlackboxed(shared)
: AllFramesOnStackAreBlackboxed();
if (ignore_break) {
// Inspector uses pause on next statement for asynchronous breakpoints.
// When breakpoint is fired we try to break on first not blackboxed
// statement. To achieve this goal we need to deoptimize current
// function and don't clear requested DebugBreak even if it's blackboxed
// to be able to break on not blackboxed function call.
// TODO(yangguo): introduce break_on_function_entry since current
// implementation is slow.
if (isolate_->stack_guard()->CheckDebugBreak()) {
Deoptimizer::DeoptimizeFunction(*function);
}
return;
}
if (ignore_break) return;
JSGlobalObject* global = function->context()->global_object();
// Don't stop in debugger functions.
if (IsDebugGlobal(global)) return;
......@@ -2225,8 +2234,6 @@ void Debug::HandleDebugBreak(IgnoreBreakMode ignore_break_mode) {
}
}
isolate_->stack_guard()->ClearDebugBreak();
// Clear stepping to avoid duplicate breaks.
ClearStepping();
......
......@@ -266,6 +266,9 @@ class Debug {
void ClearStepping();
void ClearStepOut();
void SetBreakOnNextFunctionCall();
void ClearBreakOnNextFunctionCall();
void DeoptimizeFunction(Handle<SharedFunctionInfo> shared);
void PrepareFunctionForDebugExecution(Handle<SharedFunctionInfo> shared);
void InstallDebugBreakTrampoline();
......@@ -406,6 +409,9 @@ class Debug {
}
StepAction last_step_action() { return thread_local_.last_step_action_; }
bool break_on_next_function_call() const {
return thread_local_.break_on_next_function_call_;
}
DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }
......@@ -589,6 +595,10 @@ class Debug {
// Last used inspector breakpoint id.
int last_breakpoint_id_;
// This flag is true when SetBreakOnNextFunctionCall is called and it forces
// debugger to break on next function call.
bool break_on_next_function_call_;
};
// Storage location for registers when handling debug break calls
......
......@@ -514,15 +514,6 @@ Object* StackGuard::HandleInterrupts() {
isolate_->heap()->HandleGCRequest();
}
if (CheckDebugBreak()) {
if (FLAG_trace_interrupts) {
if (any_interrupt_handled) PrintF(", ");
PrintF("DEBUG_BREAK");
any_interrupt_handled = true;
}
isolate_->debug()->HandleDebugBreak(kIgnoreIfTopFrameBlackboxed);
}
if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
if (FLAG_trace_interrupts) {
if (any_interrupt_handled) PrintF(", ");
......
......@@ -89,12 +89,11 @@ class V8_EXPORT_PRIVATE StackGuard final {
void ClearThread(const ExecutionAccess& lock);
#define INTERRUPT_LIST(V) \
V(DEBUGBREAK, DebugBreak, 0) \
V(TERMINATE_EXECUTION, TerminateExecution, 1) \
V(GC_REQUEST, GC, 2) \
V(INSTALL_CODE, InstallCode, 3) \
V(API_INTERRUPT, ApiInterrupt, 4) \
V(DEOPT_MARKED_ALLOCATION_SITES, DeoptMarkedAllocationSites, 5)
V(TERMINATE_EXECUTION, TerminateExecution, 0) \
V(GC_REQUEST, GC, 1) \
V(INSTALL_CODE, InstallCode, 2) \
V(API_INTERRUPT, ApiInterrupt, 3) \
V(DEOPT_MARKED_ALLOCATION_SITES, DeoptMarkedAllocationSites, 4)
#define V(NAME, Name, id) \
inline bool Check##Name() { return CheckInterrupt(NAME); } \
......
......@@ -477,7 +477,7 @@ Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) {
m_debugger->setBreakpointsActive(active);
if (!active && !m_breakReason.empty()) {
clearBreakDetails();
m_debugger->setPauseOnNextStatement(false, m_session->contextGroupId());
m_debugger->setPauseOnNextCall(false, m_session->contextGroupId());
}
return Response::OK();
}
......@@ -1006,7 +1006,7 @@ void V8DebuggerAgentImpl::schedulePauseOnNextStatement(
std::unique_ptr<protocol::DictionaryValue> data) {
if (isPaused() || !acceptsPause(false) || !m_breakpointsActive) return;
if (m_breakReason.empty()) {
m_debugger->setPauseOnNextStatement(true, m_session->contextGroupId());
m_debugger->setPauseOnNextCall(true, m_session->contextGroupId());
}
pushBreakDetails(breakReason, std::move(data));
}
......@@ -1014,7 +1014,7 @@ void V8DebuggerAgentImpl::schedulePauseOnNextStatement(
void V8DebuggerAgentImpl::cancelPauseOnNextStatement() {
if (isPaused() || !acceptsPause(false) || !m_breakpointsActive) return;
if (m_breakReason.size() == 1) {
m_debugger->setPauseOnNextStatement(false, m_session->contextGroupId());
m_debugger->setPauseOnNextCall(false, m_session->contextGroupId());
}
popBreakDetails();
}
......@@ -1022,10 +1022,14 @@ void V8DebuggerAgentImpl::cancelPauseOnNextStatement() {
Response V8DebuggerAgentImpl::pause() {
if (!enabled()) return Response::Error(kDebuggerNotEnabled);
if (isPaused()) return Response::OK();
if (m_debugger->canBreakProgram()) {
m_debugger->interruptAndBreak(m_session->contextGroupId());
} else {
if (m_breakReason.empty()) {
m_debugger->setPauseOnNextStatement(true, m_session->contextGroupId());
m_debugger->setPauseOnNextCall(true, m_session->contextGroupId());
}
pushBreakDetails(protocol::Debugger::Paused::ReasonEnum::Other, nullptr);
}
return Response::OK();
}
......@@ -1668,7 +1672,7 @@ void V8DebuggerAgentImpl::breakProgram(
popBreakDetails();
m_breakReason.swap(currentScheduledReason);
if (!m_breakReason.empty()) {
m_debugger->setPauseOnNextStatement(true, m_session->contextGroupId());
m_debugger->setPauseOnNextCall(true, m_session->contextGroupId());
}
}
......
......@@ -259,7 +259,7 @@ void V8Debugger::setPauseOnExceptionsState(
m_pauseOnExceptionsState = pauseOnExceptionsState;
}
void V8Debugger::setPauseOnNextStatement(bool pause, int targetContextGroupId) {
void V8Debugger::setPauseOnNextCall(bool pause, int targetContextGroupId) {
if (isPaused()) return;
DCHECK(targetContextGroupId);
if (!pause && m_targetContextGroupId &&
......@@ -269,9 +269,9 @@ void V8Debugger::setPauseOnNextStatement(bool pause, int targetContextGroupId) {
m_targetContextGroupId = targetContextGroupId;
m_breakRequested = pause;
if (pause)
v8::debug::DebugBreak(m_isolate);
v8::debug::SetBreakOnNextFunctionCall(m_isolate);
else
v8::debug::CancelDebugBreak(m_isolate);
v8::debug::ClearBreakOnNextFunctionCall(m_isolate);
}
bool V8Debugger::canBreakProgram() {
......@@ -287,6 +287,16 @@ void V8Debugger::breakProgram(int targetContextGroupId) {
v8::debug::BreakRightNow(m_isolate);
}
void V8Debugger::interruptAndBreak(int targetContextGroupId) {
// Don't allow nested breaks.
if (isPaused()) return;
DCHECK(targetContextGroupId);
m_targetContextGroupId = targetContextGroupId;
m_isolate->RequestInterrupt(
[](v8::Isolate* isolate, void*) { v8::debug::BreakRightNow(isolate); },
nullptr);
}
void V8Debugger::continueProgram(int targetContextGroupId) {
if (m_pausedContextGroupId != targetContextGroupId) return;
if (isPaused()) m_inspector->client()->quitMessageLoopOnPause();
......@@ -522,8 +532,11 @@ size_t V8Debugger::nearHeapLimitCallback(void* data, size_t current_heap_limit,
thisPtr->m_scheduledOOMBreak = true;
v8::Local<v8::Context> context = thisPtr->m_isolate->GetEnteredContext();
DCHECK(!context.IsEmpty());
thisPtr->setPauseOnNextStatement(
true, thisPtr->m_inspector->contextGroupId(context));
thisPtr->m_targetContextGroupId =
thisPtr->m_inspector->contextGroupId(context);
thisPtr->m_isolate->RequestInterrupt(
[](v8::Isolate* isolate, void*) { v8::debug::BreakRightNow(isolate); },
nullptr);
return HeapLimitForDebugging(initial_heap_limit);
}
......@@ -851,7 +864,7 @@ void V8Debugger::externalAsyncTaskStarted(const V8StackTraceId& parent) {
reinterpret_cast<uintptr_t>(m_taskWithScheduledBreak) == parent.id &&
m_taskWithScheduledBreakDebuggerId ==
debuggerIdToString(parent.debugger_id)) {
v8::debug::DebugBreak(m_isolate);
v8::debug::SetBreakOnNextFunctionCall(m_isolate);
}
}
......@@ -871,7 +884,7 @@ void V8Debugger::externalAsyncTaskFinished(const V8StackTraceId& parent) {
m_taskWithScheduledBreak = nullptr;
m_taskWithScheduledBreakDebuggerId = String16();
if (m_breakRequested) return;
v8::debug::CancelDebugBreak(m_isolate);
v8::debug::ClearBreakOnNextFunctionCall(m_isolate);
}
void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task,
......@@ -980,7 +993,7 @@ void V8Debugger::asyncTaskStartedForStepping(void* task) {
// blackboxing.
if (m_taskWithScheduledBreakDebuggerId.isEmpty() &&
task == m_taskWithScheduledBreak) {
v8::debug::DebugBreak(m_isolate);
v8::debug::SetBreakOnNextFunctionCall(m_isolate);
}
}
......@@ -991,7 +1004,7 @@ void V8Debugger::asyncTaskFinishedForStepping(void* task) {
}
m_taskWithScheduledBreak = nullptr;
if (m_breakRequested) return;
v8::debug::CancelDebugBreak(m_isolate);
v8::debug::ClearBreakOnNextFunctionCall(m_isolate);
}
void V8Debugger::asyncTaskCanceledForStepping(void* task) {
......
......@@ -49,10 +49,11 @@ class V8Debugger : public v8::debug::DebugDelegate {
void setPauseOnExceptionsState(v8::debug::ExceptionBreakState);
bool canBreakProgram();
void breakProgram(int targetContextGroupId);
void interruptAndBreak(int targetContextGroupId);
void continueProgram(int targetContextGroupId);
void breakProgramOnAssert(int targetContextGroupId);
void setPauseOnNextStatement(bool, int targetContextGroupId);
void setPauseOnNextCall(bool, int targetContextGroupId);
void stepIntoStatement(int targetContextGroupId, bool breakOnAsyncCall);
void stepOverStatement(int targetContextGroupId);
void stepOutOfFunction(int targetContextGroupId);
......
......@@ -40,7 +40,6 @@ class JsonParser BASE_EMBEDDED {
public:
V8_WARN_UNUSED_RESULT static MaybeHandle<Object> Parse(
Isolate* isolate, Handle<String> source, Handle<Object> reviver) {
PostponeInterruptsScope no_debug_breaks(isolate, StackGuard::DEBUGBREAK);
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
JsonParser(isolate, source).ParseJson(), Object);
......
......@@ -94,7 +94,6 @@ MaybeHandle<Object> JsonStringifier::Stringify(Handle<Object> object,
if (!gap->IsUndefined(isolate_) && !InitializeGap(gap)) {
return MaybeHandle<Object>();
}
PostponeInterruptsScope no_debug_breaks(isolate_, StackGuard::DEBUGBREAK);
Result result = SerializeObject(object);
if (result == UNCHANGED) return factory()->undefined_value();
if (result == SUCCESS) return builder_.Finish();
......
......@@ -129,11 +129,12 @@ RUNTIME_FUNCTION(Runtime_HandleDebuggerStatement) {
return isolate->stack_guard()->HandleInterrupts();
}
RUNTIME_FUNCTION(Runtime_ScheduleBreak) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
isolate->stack_guard()->RequestDebugBreak();
isolate->RequestInterrupt(
[](v8::Isolate* isolate, void*) { v8::debug::BreakRightNow(isolate); },
nullptr);
return isolate->heap()->undefined_value();
}
......@@ -1680,7 +1681,8 @@ RUNTIME_FUNCTION(Runtime_DebugOnFunctionCall) {
if (isolate->debug()->needs_check_on_function_call()) {
// Ensure that the callee will perform debug check on function call too.
Deoptimizer::DeoptimizeFunction(*fun);
if (isolate->debug()->last_step_action() >= StepIn) {
if (isolate->debug()->last_step_action() >= StepIn ||
isolate->debug()->break_on_next_function_call()) {
DCHECK_EQ(isolate->debug_execution_mode(), DebugInfo::kBreakpoints);
isolate->debug()->PrepareStepIn(fun);
}
......
......@@ -700,10 +700,13 @@ static void DebugEventBreak(
CcTest::CollectGarbage(v8::internal::NEW_SPACE);
// Set the break flag again to come back here as soon as possible.
v8::debug::DebugBreak(CcTest::isolate());
v8::debug::SetBreakOnNextFunctionCall(CcTest::isolate());
}
}
static void BreakRightNow(v8::Isolate* isolate, void*) {
v8::debug::BreakRightNow(isolate);
}
// Debug event handler which re-issues a debug break until a limit has been
// reached.
......@@ -724,7 +727,7 @@ static void DebugEventBreakMax(
break_point_hit_count++;
// Set the break flag again to come back here as soon as possible.
v8::debug::DebugBreak(v8_isolate);
v8_isolate->RequestInterrupt(BreakRightNow, nullptr);
} else if (terminate_after_max_break_point_hit) {
// Terminate execution after the last break if requested.
......@@ -3905,7 +3908,7 @@ TEST(DebugBreak) {
f3->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
// Set the debug break flag.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
// Call all functions with different argument count.
break_point_hit_count = 0;
......@@ -4004,7 +4007,7 @@ TEST(DebugBreakWithoutJS) {
SetDebugEventListener(isolate, DebugEventBreak);
// Set the debug break flag.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
v8::Local<v8::String> json = v8_str("[1]");
v8::Local<v8::Value> parsed = v8::JSON::Parse(context, json).ToLocalChecked();
......@@ -4036,11 +4039,11 @@ TEST(DisableBreak) {
v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
// Set, test and cancel debug break.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::CancelDebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
v8::debug::ClearBreakOnNextFunctionCall(env->GetIsolate());
// Set the debug break flag.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
// Call all functions with different argument count.
break_point_hit_count = 0;
......@@ -4048,7 +4051,7 @@ TEST(DisableBreak) {
CHECK_EQ(1, break_point_hit_count);
{
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
v8::internal::DisableBreak disable_break(isolate->debug());
f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
......@@ -4094,7 +4097,7 @@ TEST(NoBreakWhenBootstrapping) {
SetDebugEventListener(isolate, DebugEventCounter);
// Set the debug break flag.
v8::debug::DebugBreak(isolate);
v8::debug::SetBreakOnNextFunctionCall(isolate);
break_point_hit_count = 0;
{
// Create a context with an extension to make sure that some JavaScript
......@@ -5148,7 +5151,7 @@ static void DebugBreakEventListener(const v8::Debug::EventDetails& details) {
if (details.GetEvent() == v8::Break) {
event_listener_break_hit_count++;
if (event_listener_break_hit_count == 1) {
v8::debug::DebugBreak(details.GetIsolate());
details.GetIsolate()->RequestInterrupt(BreakRightNow, nullptr);
}
}
}
......@@ -5216,7 +5219,7 @@ static void DebugEventDebugBreak(
// Keep forcing breaks.
if (break_point_hit_count < 20) {
v8::debug::DebugBreak(CcTest::isolate());
v8::debug::SetBreakOnNextFunctionCall(CcTest::isolate());
}
}
}
......@@ -5247,7 +5250,7 @@ TEST(RegExpDebugBreak) {
CHECK_EQ(12, result->Int32Value(context).FromJust());
SetDebugEventListener(env->GetIsolate(), DebugEventDebugBreak);
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
result = f->Call(context, env->Global(), argc, argv).ToLocalChecked();
// Check that there was only one break event. Matching RegExp should not
......@@ -5325,7 +5328,7 @@ TEST(AfterCompileEventWhenEventListenerIsReset) {
SetDebugEventListener(env->GetIsolate(), nullptr);
SetDebugEventListener(env->GetIsolate(), AfterCompileEventListener);
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
.ToLocalChecked()
->Run(context)
......@@ -5416,7 +5419,7 @@ TEST(BreakEventWhenEventListenerIsReset) {
SetDebugEventListener(env->GetIsolate(), nullptr);
SetDebugEventListener(env->GetIsolate(), AfterCompileEventListener);
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
env->Global()
->Get(context, v8_str(env->GetIsolate(), "f"))
......@@ -5508,7 +5511,7 @@ TEST(NoDebugBreakInAfterCompileEventListener) {
SetDebugEventListener(env->GetIsolate(), BreakEventListener);
// Set the debug break flag.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
// Create a function for testing stepping.
const char* src = "function f() { eval('var x = 10;'); } ";
......@@ -5518,7 +5521,7 @@ TEST(NoDebugBreakInAfterCompileEventListener) {
CHECK_EQ(1, break_point_hit_count);
// Set the debug break flag again.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
// There should be one more break event when the script is evaluated in 'f'.
CHECK_EQ(2, break_point_hit_count);
......@@ -5547,7 +5550,7 @@ TEST(DebugBreakFunctionApply) {
SetDebugEventListener(env->GetIsolate(), DebugEventBreakMax);
// Set the debug break flag before calling the code using function.apply.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
// Limit the number of debug breaks. This is a regression test for issue 493
// where this test would enter an infinite loop.
......@@ -5705,7 +5708,7 @@ static void DebugEventBreakDeoptimize(
}
}
v8::debug::DebugBreak(CcTest::isolate());
v8::debug::SetBreakOnNextFunctionCall(CcTest::isolate());
}
}
......@@ -5736,7 +5739,7 @@ TEST(DeoptimizeDuringDebugBreak) {
.ToLocalChecked();
// Set debug break and call bar again.
v8::debug::DebugBreak(env->GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
f->Call(context, v8::Undefined(env->GetIsolate()), 0, nullptr)
.ToLocalChecked();
......@@ -5810,7 +5813,7 @@ static void DebugEventBreakWithOptimizedStack(
static void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
SetDebugEventListener(args.GetIsolate(), DebugEventBreakWithOptimizedStack);
v8::debug::DebugBreak(args.GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(args.GetIsolate());
}
......@@ -5883,7 +5886,7 @@ static void TestDebugBreakInLoop(const char* loop_head,
CompileRun(buffer.start());
// Set the debug break to enter the debugger as soon as possible.
v8::debug::DebugBreak(CcTest::isolate());
v8::debug::SetBreakOnNextFunctionCall(CcTest::isolate());
// Call function with infinite loop.
CompileRun("f();");
......@@ -6149,7 +6152,7 @@ static void DebugBreakStackTraceListener(
static void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::debug::DebugBreak(args.GetIsolate());
v8::debug::SetBreakOnNextFunctionCall(args.GetIsolate());
}
......@@ -6215,7 +6218,7 @@ TEST(DebugBreakOffThreadTerminate) {
TerminationThread terminator(isolate);
terminator.Start();
v8::TryCatch try_catch(env->GetIsolate());
v8::debug::DebugBreak(isolate);
env->GetIsolate()->RequestInterrupt(BreakRightNow, nullptr);
CompileRun("while (true);");
CHECK(try_catch.HasTerminated());
}
......
......@@ -23,7 +23,7 @@ break aux data: {
}
]
}
callback (user.js:31:17)
callback (user.js:32:2)
doFrameworkWork (framework.js:16:2)
frameworkCall (framework.js:9:12)
testFunction (user.js:27:12)
......
......@@ -13,10 +13,6 @@ Running test: testFooNotBlackboxed
result : {
}
}
foo (test.js:8:12)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
foo (test.js:9:2)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
......@@ -32,9 +28,6 @@ Running test: testFooBlackboxed
result : {
}
}
testFunction (test.js:14:21)
(anonymous) (expr.js:0:0)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
......@@ -58,10 +51,6 @@ Running test: testBooPartiallyBlackboxed1
result : {
}
}
foo (test.js:8:12)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
foo (test.js:9:2)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
......@@ -87,10 +76,6 @@ Running test: testBooPartiallyBlackboxed2
result : {
}
}
foo (test.js:8:12)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
foo (test.js:9:2)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
......@@ -116,10 +101,6 @@ Running test: testBooPartiallyBlackboxed3
result : {
}
}
foo (test.js:8:12)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
foo (test.js:9:2)
testFunction (test.js:15:2)
(anonymous) (expr.js:0:0)
......
......@@ -2,12 +2,12 @@ Checks Debugger.pause
Running test: testPause
paused at:
#var a = 42;
var a = #42;
Running test: testSkipFrameworks
paused at:
#var a = 239;
var a = #239;
Running test: testSkipOtherContext1
......@@ -17,26 +17,26 @@ var a = #1;
Running test: testSkipOtherContext2
paused at:
#var a = 239;
var a = #239;
paused at:
var a = #239;
var a = 239#;
Running test: testWithNativeBreakpoint
paused at:
#var a = 42;
var a = #42;
paused at:
#var a = 42;
var a = #42;
paused at:
#var a = 42;
var a = #42;
Running test: testResumeAnotherGroup
paused at:
#var a = 42;
var a = #42;
{
error : {
......
Checks pause inside blackboxed optimized function call.
bar (test.js:2:4)
foo (framework.js:2:15)
(anonymous) (expr.js:1:12)
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
let {session, contextGroup, Protocol} = InspectorTest.start(
'Checks pause inside blackboxed optimized function call.');
contextGroup.addScript(`
function foo() {
return 1 + bar();
}
//# sourceURL=framework.js
`);
contextGroup.addScript(`
function bar() {
return 2;
}
foo();
foo();
%OptimizeFunctionOnNextCall(foo);
foo();
//# sourceURL=test.js
`);
(async function test(){
Protocol.Debugger.enable();
Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js']});
Protocol.Runtime.evaluate({expression: `
inspector.callWithScheduledBreak(foo, 'break', '');
//# sourceURL=expr.js
`});
const {params:{callFrames}} = await Protocol.Debugger.oncePaused();
session.logCallFrames(callFrames);
InspectorTest.completeTest();
})();
......@@ -37,7 +37,7 @@ asyncCallStackTraceId is set
paused at:
debugger;
Promise.resolve().then(#v => v * 2);
Promise.resolve().then(v => v #* 2);
}
......@@ -61,7 +61,7 @@ asyncCallStackTraceId is set
paused at:
debugger;
p.then(#v => v * 2);
p.then(v => v #* 2);
resolveCallback();
......@@ -85,7 +85,7 @@ asyncCallStackTraceId is set
paused at:
debugger;
Promise.resolve().then(#v => v * 2);
Promise.resolve().then(v => v #* 2);
Promise.resolve().then(v => v * 4);
......@@ -114,7 +114,7 @@ asyncCallStackTraceId is set
paused at:
Promise.resolve().then(v => v * 2);
Promise.resolve().then(#v => v * 4);
Promise.resolve().then(v => v #* 4);
}
......@@ -155,7 +155,7 @@ asyncCallStackTraceId is set
paused at:
debugger;
Promise.resolve().then(#v => v * 4);
Promise.resolve().then(v => v #* 4);
}
......@@ -179,7 +179,7 @@ asyncCallStackTraceId is set
paused at:
debugger;
Promise.all([ Promise.resolve(), Promise.resolve() ]).then(#v => v * 2);
Promise.all([ Promise.resolve(), Promise.resolve() ]).then(v => v #* 2);
}
......@@ -203,7 +203,7 @@ asyncCallStackTraceId is set
paused at:
debugger;
createPromise().then(#v => v * 2);
createPromise().then(v => v #* 2);
}
......@@ -227,7 +227,7 @@ asyncCallStackTraceId is set
paused at:
debugger;
createPromise().then(#v => v * 2);
createPromise().then(v => v #* 2);
}
......@@ -280,7 +280,7 @@ paused at:
asyncCallStackTraceId is set
paused at:
function boo#() {
}
function boo() {
#}
}
......@@ -44,7 +44,7 @@ paused at:
}
paused at:
debugger;
Promise.resolve().then(#v => v * 2);
Promise.resolve().then(v => v #* 2);
}
......@@ -66,7 +66,7 @@ paused at:
}
paused at:
debugger;
p.then(#v => v * 2);
p.then(v => v #* 2);
resolveCallback();
......@@ -83,7 +83,7 @@ function testTwoAsyncTasks() {
}
paused at:
debugger;
Promise.resolve().then(#v => v * 2);
Promise.resolve().then(v => v #* 2);
Promise.resolve().then(v => v * 4);
......@@ -110,7 +110,7 @@ paused at:
}
paused at:
Promise.resolve().then(v => v * 2);
Promise.resolve().then(#v => v * 4);
Promise.resolve().then(v => v #* 4);
}
......@@ -142,7 +142,7 @@ paused at:
}
paused at:
debugger;
Promise.resolve().then(#v => v * 4);
Promise.resolve().then(v => v #* 4);
}
......@@ -164,7 +164,7 @@ paused at:
}
paused at:
debugger;
Promise.all([ Promise.resolve(), Promise.resolve() ]).then(#v => v * 2);
Promise.all([ Promise.resolve(), Promise.resolve() ]).then(v => v #* 2);
}
......@@ -186,6 +186,6 @@ paused at:
}
paused at:
debugger;
createPromise().then(#v => v * 2);
createPromise().then(v => v #* 2);
}
......@@ -5,7 +5,7 @@ paused at:
debugger; #setTimeout(() => 1, 0);
paused at:
debugger; setTimeout(#() => 1, 0);
debugger; setTimeout(() => #1, 0);
Running test: testDebuggerStmtBeforeCallback1
......@@ -42,5 +42,5 @@ paused at:
#setTimeout(() => 42, 0)
paused at:
setTimeout(#() => 42, 0)
setTimeout(() => #42, 0)
......@@ -3,11 +3,11 @@ Test for Debugger.stepInto with breakOnAsyncCall.
Running test: testSetTimeout
(anonymous) (test.js:0:0)
asyncCallStackTraceId is set
setTimeout (test.js:0:11)
setTimeout (test.js:0:17)
asyncCallStackTraceId is empty
Running test: testPromiseThen
(anonymous) (test.js:0:2)
asyncCallStackTraceId is set
p.then (test.js:0:7)
p.then (test.js:0:13)
asyncCallStackTraceId is empty
......@@ -5,7 +5,7 @@ Run stepInto with breakOnAsyncCall flag
Call pauseOnAsyncCall
Trigger external async task on another context group
Dump stack trace
boo (target.js:1:18)
boo (target.js:1:22)
call (framework.js:3:2)
(anonymous) (target.js:0:0)
-- remote-task --
......
......@@ -5,7 +5,7 @@ Run stepInto with breakOnAsyncCall flag
Call pauseOnAsyncCall
Trigger external async task on another context group
Dump stack trace
boo (target.js:1:18)
boo (target.js:1:22)
call (framework.js:3:2)
(anonymous) (target.js:0:0)
-- remote-task --
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment