[inspector] speedup Debugger.getPossibleBreakpoints

In current implementation we call PrepareForBreakPoints during getting possible breakpoints, this call produce GC and iteration through heap, but it's not needed before we set real breakpoint.

On my machine, get-possible-breakpoints-master.js without CL takes ~200ms, with CL it takes ~60 ms. Running test without getPossibleBreakpoints protocol call takes ~50 ms. It means that we have (200-50)/(60-50) = 15 times faster getPossibleBreakpoints.

R=yangguo@chromium.org,jgrubber@chromium.org

Bug: none
Change-Id: If12e41cd87dbba11a89aa5895e3b4d88123d7d3d
Reviewed-on: https://chromium-review.googlesource.com/591027
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47021}
This commit is contained in:
Alexey Kozyatinskiy 2017-07-31 11:02:01 -07:00 committed by Commit Bot
parent 6fbbe93c5e
commit f455986fc1
3 changed files with 22 additions and 7 deletions

View File

@ -666,6 +666,7 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function,
// Make sure the function is compiled and has set up the debug info.
Handle<SharedFunctionInfo> shared(function->shared());
if (!EnsureBreakInfo(shared)) return true;
CHECK(PrepareFunctionForBreakPoints(shared));
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
// Source positions starts with zero.
DCHECK(*source_position >= 0);
@ -703,6 +704,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
// Make sure the function has set up the debug info.
Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
if (!EnsureBreakInfo(shared)) return false;
CHECK(PrepareFunctionForBreakPoints(shared));
// Find position within function. The script position might be before the
// source position of the first function.
@ -810,6 +812,7 @@ void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared,
if (IsBlackboxed(shared)) return;
// Make sure the function is compiled and has set up the debug info.
if (!EnsureBreakInfo(shared)) return;
CHECK(PrepareFunctionForBreakPoints(shared));
Handle<DebugInfo> debug_info(shared->GetDebugInfo());
// Flood the function with break points.
if (debug_info->HasDebugCode()) {
@ -1254,7 +1257,14 @@ class RedirectActiveFunctions : public ThreadVisitor {
bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
// To prepare bytecode for debugging, we already need to have the debug
// info (containing the debug copy) upfront, but since we do not recompile,
// preparing for break points cannot fail.
DCHECK(shared->is_compiled());
DCHECK(shared->HasDebugInfo());
DCHECK(shared->HasBreakInfo());
Handle<DebugInfo> debug_info = GetOrCreateDebugInfo(shared);
if (debug_info->IsPreparedForBreakpoints()) return true;
if (isolate_->concurrent_recompilation_enabled()) {
isolate_->optimizing_compile_dispatcher()->Flush(
@ -1311,6 +1321,8 @@ bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
debug_info->set_flags(debug_info->flags() |
DebugInfo::kPreparedForBreakpoints);
return true;
}
@ -1519,12 +1531,7 @@ bool Debug::EnsureBreakInfo(Handle<SharedFunctionInfo> shared) {
if (!shared->is_compiled() && !Compiler::CompileDebugCode(shared)) {
return false;
}
// To prepare bytecode for debugging, we already need to have the debug
// info (containing the debug copy) upfront, but since we do not recompile,
// preparing for break points cannot fail.
CreateBreakInfo(shared);
CHECK(PrepareFunctionForBreakPoints(shared));
return true;
}

View File

@ -12,13 +12,18 @@ bool DebugInfo::IsEmpty() const { return flags() == kNone; }
bool DebugInfo::HasBreakInfo() const { return (flags() & kHasBreakInfo) != 0; }
bool DebugInfo::IsPreparedForBreakpoints() const {
DCHECK(HasBreakInfo());
return (flags() & kPreparedForBreakpoints) != 0;
}
bool DebugInfo::ClearBreakInfo() {
Isolate* isolate = GetIsolate();
set_debug_bytecode_array(isolate->heap()->undefined_value());
set_break_points(isolate->heap()->empty_fixed_array());
int new_flags = flags() & ~kHasBreakInfo;
int new_flags = flags() & ~kHasBreakInfo & ~kPreparedForBreakpoints;
set_flags(new_flags);
return new_flags == kNone;

View File

@ -20,7 +20,8 @@ class DebugInfo : public Struct {
enum Flag {
kNone = 0,
kHasBreakInfo = 1 << 0,
kHasCoverageInfo = 1 << 1,
kPreparedForBreakpoints = 1 << 1,
kHasCoverageInfo = 2 << 1,
};
typedef base::Flags<Flag> Flags;
@ -41,6 +42,8 @@ class DebugInfo : public Struct {
bool HasBreakInfo() const;
bool IsPreparedForBreakpoints() const;
// Clears all fields related to break points. Returns true iff the
// DebugInfo is now empty.
bool ClearBreakInfo();