[vm/debugger] Use RwLock instead of SafepointRwLock, get rid of RunUnderLockIfNeeded.
RwLock, rather that SafepointRwLock, is okay to use for these two breakpoint_locations and single_stepping_set locks because they are short-lived, should not spawn over the safepoint. TEST=ci Change-Id: Iba83291978ba7980d0c6fd0a0a2cf2174c801359 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323202 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Aprelev <aam@google.com>
This commit is contained in:
committed by
Commit Queue
parent
2c9089f120
commit
2f457d1a8a
+28
-41
@@ -1374,8 +1374,8 @@ GroupDebugger::GroupDebugger(IsolateGroup* isolate_group)
|
||||
: isolate_group_(isolate_group),
|
||||
code_breakpoints_lock_(new RwLock()),
|
||||
code_breakpoints_(nullptr),
|
||||
breakpoint_locations_lock_(new SafepointRwLock()),
|
||||
single_stepping_set_lock_(new SafepointRwLock()),
|
||||
breakpoint_locations_lock_(new RwLock()),
|
||||
single_stepping_set_lock_(new RwLock()),
|
||||
needs_breakpoint_cleanup_(false) {}
|
||||
|
||||
GroupDebugger::~GroupDebugger() {
|
||||
@@ -1420,8 +1420,8 @@ void Debugger::Shutdown() {
|
||||
return;
|
||||
}
|
||||
{
|
||||
SafepointWriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
WriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
while (breakpoint_locations_ != nullptr) {
|
||||
BreakpointLocation* loc = breakpoint_locations_;
|
||||
group_debugger()->UnlinkCodeBreakpoints(loc);
|
||||
@@ -3328,32 +3328,19 @@ void GroupDebugger::UnregisterSingleSteppingDebugger(Thread* thread,
|
||||
single_stepping_set_.Remove(debugger);
|
||||
}
|
||||
|
||||
bool GroupDebugger::RunUnderReadLockIfNeededCallable(Thread* thread,
|
||||
SafepointRwLock* rw_lock,
|
||||
BoolCallable* callable) {
|
||||
if (thread->IsInStoppedMutatorsScope()) {
|
||||
return callable->Call();
|
||||
}
|
||||
|
||||
SafepointReadRwLocker sl(thread, rw_lock);
|
||||
return callable->Call();
|
||||
}
|
||||
|
||||
bool GroupDebugger::HasBreakpoint(Thread* thread, const Function& function) {
|
||||
if (RunUnderReadLockIfNeeded(thread, breakpoint_locations_lock(), [&]() {
|
||||
// Check if function has any breakpoints.
|
||||
String& url = String::Handle(thread->zone());
|
||||
for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
|
||||
BreakpointLocation* location = breakpoint_locations_.At(i);
|
||||
url = location->url();
|
||||
if (FunctionOverlaps(function, url, location->token_pos(),
|
||||
location->end_token_pos())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})) {
|
||||
return true;
|
||||
{
|
||||
ReadRwLocker(thread, breakpoint_locations_lock());
|
||||
// Check if function has any breakpoints.
|
||||
String& url = String::Handle(thread->zone());
|
||||
for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
|
||||
BreakpointLocation* location = breakpoint_locations_.At(i);
|
||||
url = location->url();
|
||||
if (FunctionOverlaps(function, url, location->token_pos(),
|
||||
location->end_token_pos())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(aam): do we have to iterate over both code breakpoints and
|
||||
@@ -3368,18 +3355,18 @@ bool GroupDebugger::HasBreakpoint(Thread* thread, const Function& function) {
|
||||
}
|
||||
|
||||
bool GroupDebugger::IsDebugging(Thread* thread, const Function& function) {
|
||||
if (!RunUnderReadLockIfNeeded(thread, single_stepping_set_lock(), [&]() {
|
||||
return single_stepping_set_.IsEmpty();
|
||||
})) {
|
||||
return true;
|
||||
{
|
||||
ReadRwLocker ml(thread, single_stepping_set_lock());
|
||||
if (!single_stepping_set_.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return HasBreakpoint(thread, function);
|
||||
}
|
||||
|
||||
void Debugger::set_resume_action(ResumeAction resume_action) {
|
||||
auto thread = Thread::Current();
|
||||
SafepointWriteRwLocker sl(thread,
|
||||
group_debugger()->single_stepping_set_lock());
|
||||
WriteRwLocker sl(thread, group_debugger()->single_stepping_set_lock());
|
||||
if (resume_action == kContinue) {
|
||||
group_debugger()->UnregisterSingleSteppingDebugger(thread, this);
|
||||
} else {
|
||||
@@ -3831,8 +3818,8 @@ CodePtr GroupDebugger::GetPatchedStubAddress(uword breakpoint_address) {
|
||||
}
|
||||
|
||||
bool Debugger::SetBreakpointState(Breakpoint* bpt, bool enable) {
|
||||
SafepointWriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
WriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
if (bpt->is_enabled() != enable) {
|
||||
if (FLAG_verbose_debug) {
|
||||
OS::PrintErr("Setting breakpoint %" Pd " to state: %s\n", bpt->id(),
|
||||
@@ -3848,8 +3835,8 @@ bool Debugger::SetBreakpointState(Breakpoint* bpt, bool enable) {
|
||||
// Remove and delete the source breakpoint bpt and its associated
|
||||
// code breakpoints.
|
||||
void Debugger::RemoveBreakpoint(intptr_t bp_id) {
|
||||
SafepointWriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
WriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
if (RemoveBreakpointFromTheList(bp_id, &breakpoint_locations_)) {
|
||||
return;
|
||||
}
|
||||
@@ -4084,8 +4071,8 @@ BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url,
|
||||
}
|
||||
|
||||
void Debugger::RegisterBreakpointLocation(BreakpointLocation* loc) {
|
||||
SafepointWriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
WriteRwLocker sl(Thread::Current(),
|
||||
group_debugger()->breakpoint_locations_lock());
|
||||
ASSERT(loc->next() == nullptr);
|
||||
loc->set_next(breakpoint_locations_);
|
||||
breakpoint_locations_ = loc;
|
||||
|
||||
+5
-18
@@ -611,29 +611,16 @@ class GroupDebugger {
|
||||
|
||||
RwLock* code_breakpoints_lock() { return code_breakpoints_lock_.get(); }
|
||||
|
||||
SafepointRwLock* breakpoint_locations_lock() {
|
||||
RwLock* breakpoint_locations_lock() {
|
||||
return breakpoint_locations_lock_.get();
|
||||
}
|
||||
|
||||
SafepointRwLock* single_stepping_set_lock() {
|
||||
return single_stepping_set_lock_.get();
|
||||
}
|
||||
RwLock* single_stepping_set_lock() { return single_stepping_set_lock_.get(); }
|
||||
|
||||
void RegisterSingleSteppingDebugger(Thread* thread, const Debugger* debugger);
|
||||
void UnregisterSingleSteppingDebugger(Thread* thread,
|
||||
const Debugger* debugger);
|
||||
|
||||
bool RunUnderReadLockIfNeededCallable(Thread* thread,
|
||||
SafepointRwLock* rw_lock,
|
||||
BoolCallable* callable);
|
||||
|
||||
template <typename T>
|
||||
bool RunUnderReadLockIfNeeded(Thread* thread,
|
||||
SafepointRwLock* rw_lock,
|
||||
T function) {
|
||||
LambdaBoolCallable<T> callable(function);
|
||||
return RunUnderReadLockIfNeededCallable(thread, rw_lock, &callable);
|
||||
}
|
||||
|
||||
// Returns [true] if there is at least one breakpoint set in function or code.
|
||||
// Checks for both user-defined and internal temporary breakpoints.
|
||||
bool HasBreakpoint(Thread* thread, const Function& function);
|
||||
@@ -648,10 +635,10 @@ class GroupDebugger {
|
||||
// Secondary list of all breakpoint_locations_(primary is in Debugger class).
|
||||
// This list is kept in sync with all the lists in Isolate Debuggers and is
|
||||
// used to quickly scan BreakpointLocations when new Function is compiled.
|
||||
std::unique_ptr<SafepointRwLock> breakpoint_locations_lock_;
|
||||
std::unique_ptr<RwLock> breakpoint_locations_lock_;
|
||||
MallocGrowableArray<BreakpointLocation*> breakpoint_locations_;
|
||||
|
||||
std::unique_ptr<SafepointRwLock> single_stepping_set_lock_;
|
||||
std::unique_ptr<RwLock> single_stepping_set_lock_;
|
||||
DebuggerSet single_stepping_set_;
|
||||
|
||||
void RemoveUnlinkedCodeBreakpoints();
|
||||
|
||||
Reference in New Issue
Block a user