Cleanup JDWP event matching
* Use std::vector for the event match list.
* Make event reporting methods void since result is never used.
* Use nullptr keyword instead of NULL.
Change-Id: Icd6f47e46cefc2cc63325df00037cd4b6a475259
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index 1e0a2d2..1bf16b2 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -172,9 +172,9 @@
* not be added to the list, and an appropriate error will be returned.
*/
JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
- CHECK(pEvent != NULL);
- CHECK(pEvent->prev == NULL);
- CHECK(pEvent->next == NULL);
+ CHECK(pEvent != nullptr);
+ CHECK(pEvent->prev == nullptr);
+ CHECK(pEvent->next == nullptr);
{
/*
@@ -223,7 +223,7 @@
* Add to list.
*/
MutexLock mu(Thread::Current(), event_list_lock_);
- if (event_list_ != NULL) {
+ if (event_list_ != nullptr) {
pEvent->next = event_list_;
event_list_->prev = pEvent;
}
@@ -245,7 +245,7 @@
* Grab the eventLock before calling here.
*/
void JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
- if (pEvent->prev == NULL) {
+ if (pEvent->prev == nullptr) {
/* head of the list */
CHECK(event_list_ == pEvent);
@@ -254,11 +254,11 @@
pEvent->prev->next = pEvent->next;
}
- if (pEvent->next != NULL) {
+ if (pEvent->next != nullptr) {
pEvent->next->prev = pEvent->prev;
- pEvent->next = NULL;
+ pEvent->next = nullptr;
}
- pEvent->prev = NULL;
+ pEvent->prev = nullptr;
{
/*
@@ -303,7 +303,7 @@
}
--event_list_size_;
- CHECK(event_list_size_ != 0 || event_list_ == NULL);
+ CHECK(event_list_size_ != 0 || event_list_ == nullptr);
}
/*
@@ -343,7 +343,7 @@
MutexLock mu(Thread::Current(), event_list_lock_);
JdwpEvent* pEvent = event_list_;
- while (pEvent != NULL) {
+ while (pEvent != nullptr) {
JdwpEvent* pNextEvent = pEvent->next;
UnregisterEvent(pEvent);
@@ -351,7 +351,7 @@
pEvent = pNextEvent;
}
- event_list_ = NULL;
+ event_list_ = nullptr;
}
/*
@@ -372,13 +372,13 @@
* Do not call this until the event has been removed from the list.
*/
void EventFree(JdwpEvent* pEvent) {
- if (pEvent == NULL) {
+ if (pEvent == nullptr) {
return;
}
/* make sure it was removed from the list */
- CHECK(pEvent->prev == NULL);
- CHECK(pEvent->next == NULL);
+ CHECK(pEvent->prev == nullptr);
+ CHECK(pEvent->next == nullptr);
/* want to check state->event_list_ != pEvent */
/*
@@ -387,11 +387,11 @@
for (int i = 0; i < pEvent->modCount; i++) {
if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
free(pEvent->mods[i].classMatch.classPattern);
- pEvent->mods[i].classMatch.classPattern = NULL;
+ pEvent->mods[i].classMatch.classPattern = nullptr;
}
if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
free(pEvent->mods[i].classExclude.classPattern);
- pEvent->mods[i].classExclude.classPattern = NULL;
+ pEvent->mods[i].classExclude.classPattern = nullptr;
}
}
@@ -399,26 +399,12 @@
}
/*
- * Allocate storage for matching events. To keep things simple we
- * use an array with enough storage for the entire list.
- *
- * The state->eventLock should be held before calling.
- */
-static JdwpEvent** AllocMatchList(size_t event_count) {
- return new JdwpEvent*[event_count];
-}
-
-/*
* Run through the list and remove any entries with an expired "count" mod
- * from the event list, then free the match list.
+ * from the event list.
*/
-void JdwpState::CleanupMatchList(JdwpEvent** match_list, size_t match_count) {
- JdwpEvent** ppEvent = match_list;
-
- while (match_count--) {
- JdwpEvent* pEvent = *ppEvent;
-
- for (int i = 0; i < pEvent->modCount; i++) {
+void JdwpState::CleanupMatchList(const std::vector<JdwpEvent*>& match_list) {
+ for (JdwpEvent* pEvent : match_list) {
+ for (int i = 0; i < pEvent->modCount; ++i) {
if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
VLOG(jdwp) << StringPrintf("##### Removing expired event (requestId=%#" PRIx32 ")",
pEvent->requestId);
@@ -427,11 +413,7 @@
break;
}
}
-
- ppEvent++;
}
-
- delete[] match_list;
}
/*
@@ -536,40 +518,55 @@
}
/*
- * Find all events of type "eventKind" with mods that match up with the
- * rest of the arguments.
+ * Find all events of type "event_kind" with mods that match up with the
+ * rest of the arguments while holding the event list lock. This method
+ * is used by FindMatchingEvents below.
*
- * Found events are appended to "match_list", and "*pMatchCount" is advanced,
- * so this may be called multiple times for grouped events.
+ * Found events are appended to "match_list" so this may be called multiple times for grouped
+ * events.
*
* DO NOT call this multiple times for the same eventKind, as Count mods are
* decremented during the scan.
*/
-void JdwpState::FindMatchingEvents(JdwpEventKind eventKind, const ModBasket& basket,
- JdwpEvent** match_list, size_t* pMatchCount) {
- /* start after the existing entries */
- match_list += *pMatchCount;
-
+void JdwpState::FindMatchingEventsLocked(JdwpEventKind event_kind, const ModBasket& basket,
+ std::vector<JdwpEvent*>* match_list) {
for (JdwpEvent* pEvent = event_list_; pEvent != nullptr; pEvent = pEvent->next) {
- if (pEvent->eventKind == eventKind && ModsMatch(pEvent, basket)) {
- *match_list++ = pEvent;
- (*pMatchCount)++;
+ if (pEvent->eventKind == event_kind && ModsMatch(pEvent, basket)) {
+ match_list->push_back(pEvent);
}
}
}
/*
+ * Find all events of type "event_kind" with mods that match up with the
+ * rest of the arguments and return true if at least one event matches,
+ * false otherwise.
+ *
+ * Found events are appended to "match_list" so this may be called multiple
+ * times for grouped events.
+ *
+ * DO NOT call this multiple times for the same eventKind, as Count mods are
+ * decremented during the scan.
+ */
+bool JdwpState::FindMatchingEvents(JdwpEventKind event_kind, const ModBasket& basket,
+ std::vector<JdwpEvent*>* match_list) {
+ MutexLock mu(Thread::Current(), event_list_lock_);
+ match_list->reserve(event_list_size_);
+ FindMatchingEventsLocked(event_kind, basket, match_list);
+ return !match_list->empty();
+}
+
+/*
* Scan through the list of matches and determine the most severe
* suspension policy.
*/
-static JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** match_list, int match_count) {
+static JdwpSuspendPolicy ScanSuspendPolicy(const std::vector<JdwpEvent*>& match_list) {
JdwpSuspendPolicy policy = SP_NONE;
- while (match_count--) {
- if ((*match_list)->suspend_policy > policy) {
- policy = (*match_list)->suspend_policy;
+ for (JdwpEvent* pEvent : match_list) {
+ if (pEvent->suspend_policy > policy) {
+ policy = pEvent->suspend_policy;
}
- match_list++;
}
return policy;
@@ -626,19 +623,18 @@
void JdwpState::SendRequestAndPossiblySuspend(ExpandBuf* pReq, JdwpSuspendPolicy suspend_policy,
ObjectId threadId) {
- Thread* self = Thread::Current();
+ Thread* const self = Thread::Current();
self->AssertThreadSuspensionIsAllowable();
+ CHECK(pReq != nullptr);
/* send request and possibly suspend ourselves */
- if (pReq != NULL) {
- JDWP::ObjectId thread_self_id = Dbg::GetThreadSelfId();
- self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
- if (suspend_policy != SP_NONE) {
- SetWaitForEventThread(threadId);
- }
- EventFinish(pReq);
- SuspendByPolicy(suspend_policy, thread_self_id);
- self->TransitionFromSuspendedToRunnable();
+ JDWP::ObjectId thread_self_id = Dbg::GetThreadSelfId();
+ self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
+ if (suspend_policy != SP_NONE) {
+ SetWaitForEventThread(threadId);
}
+ EventFinish(pReq);
+ SuspendByPolicy(suspend_policy, thread_self_id);
+ self->TransitionFromSuspendedToRunnable();
}
/*
@@ -729,10 +725,10 @@
uint8_t* buf = expandBufGetBuffer(pReq);
Set4BE(buf, expandBufGetLength(pReq));
- Set4BE(buf+4, NextRequestSerial());
- Set1(buf+8, 0); /* flags */
- Set1(buf+9, kJdwpEventCommandSet);
- Set1(buf+10, kJdwpCompositeCommand);
+ Set4BE(buf + 4, NextRequestSerial());
+ Set1(buf + 8, 0); /* flags */
+ Set1(buf + 9, kJdwpEventCommandSet);
+ Set1(buf + 10, kJdwpCompositeCommand);
// Prevents from interleaving commands and events. Otherwise we could end up in sending an event
// before sending the reply of the command being processed and would lead to bad synchronization
@@ -753,43 +749,30 @@
* any application code has been executed". The thread ID in the message
* must be for the main thread.
*/
-bool JdwpState::PostVMStart() {
- JdwpSuspendPolicy suspend_policy;
+void JdwpState::PostVMStart() {
+ JdwpSuspendPolicy suspend_policy = (options_->suspend) ? SP_ALL : SP_NONE;
ObjectId threadId = Dbg::GetThreadSelfId();
- if (options_->suspend) {
- suspend_policy = SP_ALL;
- } else {
- suspend_policy = SP_NONE;
- }
+ VLOG(jdwp) << "EVENT: " << EK_VM_START;
+ VLOG(jdwp) << " suspend_policy=" << suspend_policy;
ExpandBuf* pReq = eventPrep();
- {
- MutexLock mu(Thread::Current(), event_list_lock_); // probably don't need this here
-
- VLOG(jdwp) << "EVENT: " << EK_VM_START;
- VLOG(jdwp) << " suspend_policy=" << suspend_policy;
-
- expandBufAdd1(pReq, suspend_policy);
- expandBufAdd4BE(pReq, 1);
-
- expandBufAdd1(pReq, EK_VM_START);
- expandBufAdd4BE(pReq, 0); /* requestId */
- expandBufAdd8BE(pReq, threadId);
- }
+ expandBufAdd1(pReq, suspend_policy);
+ expandBufAdd4BE(pReq, 1);
+ expandBufAdd1(pReq, EK_VM_START);
+ expandBufAdd4BE(pReq, 0); /* requestId */
+ expandBufAddObjectId(pReq, threadId);
Dbg::ManageDeoptimization();
/* send request and possibly suspend ourselves */
SendRequestAndPossiblySuspend(pReq, suspend_policy, threadId);
-
- return true;
}
-static void LogMatchingEventsAndThread(JdwpEvent** match_list, size_t match_count,
+static void LogMatchingEventsAndThread(const std::vector<JdwpEvent*> match_list,
ObjectId thread_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- for (size_t i = 0; i < match_count; ++i) {
+ for (size_t i = 0, e = match_list.size(); i < e; ++i) {
JdwpEvent* pEvent = match_list[i];
VLOG(jdwp) << "EVENT #" << i << ": " << pEvent->eventKind
<< StringPrintf(" (requestId=%#" PRIx32 ")", pEvent->requestId);
@@ -831,7 +814,7 @@
* - Single-step to a line with a breakpoint. Should get a single
* event message with both events in it.
*/
-bool JdwpState::PostLocationEvent(const EventLocation* pLoc, mirror::Object* thisPtr,
+void JdwpState::PostLocationEvent(const EventLocation* pLoc, mirror::Object* thisPtr,
int eventFlags, const JValue* returnValue) {
DCHECK(pLoc != nullptr);
DCHECK(pLoc->method != nullptr);
@@ -852,7 +835,7 @@
*/
if (basket.thread == GetDebugThread()) {
VLOG(jdwp) << "Ignoring location event in JDWP thread";
- return false;
+ return;
}
/*
@@ -866,73 +849,69 @@
*/
if (InvokeInProgress()) {
VLOG(jdwp) << "Not checking breakpoints during invoke (" << basket.className << ")";
- return false;
+ return;
}
- size_t match_count = 0;
- ExpandBuf* pReq = NULL;
- JdwpSuspendPolicy suspend_policy = SP_NONE;
- JdwpEvent** match_list = nullptr;
- ObjectId thread_id = 0;
+ std::vector<JdwpEvent*> match_list;
{
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- match_list = AllocMatchList(event_list_size_);
- if ((eventFlags & Dbg::kBreakpoint) != 0) {
- FindMatchingEvents(EK_BREAKPOINT, basket, match_list, &match_count);
- }
- if ((eventFlags & Dbg::kSingleStep) != 0) {
- FindMatchingEvents(EK_SINGLE_STEP, basket, match_list, &match_count);
- }
- if ((eventFlags & Dbg::kMethodEntry) != 0) {
- FindMatchingEvents(EK_METHOD_ENTRY, basket, match_list, &match_count);
- }
- if ((eventFlags & Dbg::kMethodExit) != 0) {
- FindMatchingEvents(EK_METHOD_EXIT, basket, match_list, &match_count);
- FindMatchingEvents(EK_METHOD_EXIT_WITH_RETURN_VALUE, basket, match_list, &match_count);
- }
+ // We use the locked version because we have multiple possible match events.
+ MutexLock mu(Thread::Current(), event_list_lock_);
+ match_list.reserve(event_list_size_);
+ if ((eventFlags & Dbg::kBreakpoint) != 0) {
+ FindMatchingEventsLocked(EK_BREAKPOINT, basket, &match_list);
}
- if (match_count != 0) {
- suspend_policy = scanSuspendPolicy(match_list, match_count);
-
- thread_id = Dbg::GetThreadId(basket.thread);
- JDWP::JdwpLocation jdwp_location;
- SetJdwpLocationFromEventLocation(pLoc, &jdwp_location);
-
- if (VLOG_IS_ON(jdwp)) {
- LogMatchingEventsAndThread(match_list, match_count, thread_id);
- VLOG(jdwp) << " location=" << jdwp_location;
- VLOG(jdwp) << " suspend_policy=" << suspend_policy;
- }
-
- pReq = eventPrep();
- expandBufAdd1(pReq, suspend_policy);
- expandBufAdd4BE(pReq, match_count);
-
- for (size_t i = 0; i < match_count; i++) {
- expandBufAdd1(pReq, match_list[i]->eventKind);
- expandBufAdd4BE(pReq, match_list[i]->requestId);
- expandBufAdd8BE(pReq, thread_id);
- expandBufAddLocation(pReq, jdwp_location);
- if (match_list[i]->eventKind == EK_METHOD_EXIT_WITH_RETURN_VALUE) {
- Dbg::OutputMethodReturnValue(jdwp_location.method_id, returnValue, pReq);
- }
- }
+ if ((eventFlags & Dbg::kSingleStep) != 0) {
+ FindMatchingEventsLocked(EK_SINGLE_STEP, basket, &match_list);
}
-
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- CleanupMatchList(match_list, match_count);
+ if ((eventFlags & Dbg::kMethodEntry) != 0) {
+ FindMatchingEventsLocked(EK_METHOD_ENTRY, basket, &match_list);
}
+ if ((eventFlags & Dbg::kMethodExit) != 0) {
+ FindMatchingEventsLocked(EK_METHOD_EXIT, basket, &match_list);
+ FindMatchingEventsLocked(EK_METHOD_EXIT_WITH_RETURN_VALUE, basket, &match_list);
+ }
+ }
+ if (match_list.empty()) {
+ // No matching event.
+ return;
+ }
+ JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
+
+ ObjectId thread_id = Dbg::GetThreadId(basket.thread);
+ JDWP::JdwpLocation jdwp_location;
+ SetJdwpLocationFromEventLocation(pLoc, &jdwp_location);
+
+ if (VLOG_IS_ON(jdwp)) {
+ LogMatchingEventsAndThread(match_list, thread_id);
+ VLOG(jdwp) << " location=" << jdwp_location;
+ VLOG(jdwp) << " suspend_policy=" << suspend_policy;
+ }
+
+ ExpandBuf* pReq = eventPrep();
+ expandBufAdd1(pReq, suspend_policy);
+ expandBufAdd4BE(pReq, match_list.size());
+
+ for (const JdwpEvent* pEvent : match_list) {
+ expandBufAdd1(pReq, pEvent->eventKind);
+ expandBufAdd4BE(pReq, pEvent->requestId);
+ expandBufAddObjectId(pReq, thread_id);
+ expandBufAddLocation(pReq, jdwp_location);
+ if (pEvent->eventKind == EK_METHOD_EXIT_WITH_RETURN_VALUE) {
+ Dbg::OutputMethodReturnValue(jdwp_location.method_id, returnValue, pReq);
+ }
+ }
+
+ {
+ MutexLock mu(Thread::Current(), event_list_lock_);
+ CleanupMatchList(match_list);
}
Dbg::ManageDeoptimization();
SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
- return match_count != 0;
}
-bool JdwpState::PostFieldEvent(const EventLocation* pLoc, mirror::ArtField* field,
+void JdwpState::PostFieldEvent(const EventLocation* pLoc, mirror::ArtField* field,
mirror::Object* this_object, const JValue* fieldValue,
bool is_modification) {
DCHECK(pLoc != nullptr);
@@ -950,86 +929,73 @@
if (InvokeInProgress()) {
VLOG(jdwp) << "Not posting field event during invoke";
- return false;
+ return;
}
- size_t match_count = 0;
- ExpandBuf* pReq = NULL;
- JdwpSuspendPolicy suspend_policy = SP_NONE;
- JdwpEvent** match_list = nullptr;
- ObjectId thread_id = 0;
+ std::vector<JdwpEvent*> match_list;
+ const JdwpEventKind match_kind = (is_modification) ? EK_FIELD_MODIFICATION : EK_FIELD_ACCESS;
+ if (!FindMatchingEvents(match_kind, basket, &match_list)) {
+ // No matching event.
+ return;
+ }
+
+ JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
+ ObjectId thread_id = Dbg::GetThreadId(basket.thread);
+ ObjectRegistry* registry = Dbg::GetObjectRegistry();
+ ObjectId instance_id = registry->Add(basket.thisPtr);
+ RefTypeId field_type_id = registry->AddRefType(field->GetDeclaringClass());
+ FieldId field_id = Dbg::ToFieldId(field);
+ JDWP::JdwpLocation jdwp_location;
+ SetJdwpLocationFromEventLocation(pLoc, &jdwp_location);
+
+ if (VLOG_IS_ON(jdwp)) {
+ LogMatchingEventsAndThread(match_list, thread_id);
+ VLOG(jdwp) << " location=" << jdwp_location;
+ VLOG(jdwp) << StringPrintf(" this=%#" PRIx64, instance_id);
+ VLOG(jdwp) << StringPrintf(" type=%#" PRIx64, field_type_id) << " "
+ << Dbg::GetClassName(field_id);
+ VLOG(jdwp) << StringPrintf(" field=%#" PRIx32, field_id) << " "
+ << Dbg::GetFieldName(field_id);
+ VLOG(jdwp) << " suspend_policy=" << suspend_policy;
+ }
+
+ ExpandBuf* pReq = eventPrep();
+ expandBufAdd1(pReq, suspend_policy);
+ expandBufAdd4BE(pReq, match_list.size());
+
+ // Get field's reference type tag.
+ JDWP::JdwpTypeTag type_tag = Dbg::GetTypeTag(field->GetDeclaringClass());
+
+ // Get instance type tag.
+ uint8_t tag;
{
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- match_list = AllocMatchList(event_list_size_);
- if (is_modification) {
- FindMatchingEvents(EK_FIELD_MODIFICATION, basket, match_list, &match_count);
- } else {
- FindMatchingEvents(EK_FIELD_ACCESS, basket, match_list, &match_count);
- }
+ ScopedObjectAccessUnchecked soa(Thread::Current());
+ tag = Dbg::TagFromObject(soa, basket.thisPtr);
+ }
+
+ for (const JdwpEvent* pEvent : match_list) {
+ expandBufAdd1(pReq, pEvent->eventKind);
+ expandBufAdd4BE(pReq, pEvent->requestId);
+ expandBufAddObjectId(pReq, thread_id);
+ expandBufAddLocation(pReq, jdwp_location);
+ expandBufAdd1(pReq, type_tag);
+ expandBufAddRefTypeId(pReq, field_type_id);
+ expandBufAddFieldId(pReq, field_id);
+ expandBufAdd1(pReq, tag);
+ expandBufAddObjectId(pReq, instance_id);
+ if (is_modification) {
+ Dbg::OutputFieldValue(field_id, fieldValue, pReq);
}
- if (match_count != 0) {
- suspend_policy = scanSuspendPolicy(match_list, match_count);
+ }
- thread_id = Dbg::GetThreadId(basket.thread);
- ObjectRegistry* registry = Dbg::GetObjectRegistry();
- ObjectId instance_id = registry->Add(basket.thisPtr);
- RefTypeId field_type_id = registry->AddRefType(field->GetDeclaringClass());
- FieldId field_id = Dbg::ToFieldId(field);
- JDWP::JdwpLocation jdwp_location;
- SetJdwpLocationFromEventLocation(pLoc, &jdwp_location);
-
- if (VLOG_IS_ON(jdwp)) {
- LogMatchingEventsAndThread(match_list, match_count, thread_id);
- VLOG(jdwp) << " location=" << jdwp_location;
- VLOG(jdwp) << StringPrintf(" this=%#" PRIx64, instance_id);
- VLOG(jdwp) << StringPrintf(" type=%#" PRIx64, field_type_id) << " "
- << Dbg::GetClassName(field_id);
- VLOG(jdwp) << StringPrintf(" field=%#" PRIx32, field_id) << " "
- << Dbg::GetFieldName(field_id);
- VLOG(jdwp) << " suspend_policy=" << suspend_policy;
- }
-
- pReq = eventPrep();
- expandBufAdd1(pReq, suspend_policy);
- expandBufAdd4BE(pReq, match_count);
-
- // Get field's reference type tag.
- JDWP::JdwpTypeTag type_tag = Dbg::GetTypeTag(field->GetDeclaringClass());
-
- // Get instance type tag.
- uint8_t tag;
- {
- ScopedObjectAccessUnchecked soa(Thread::Current());
- tag = Dbg::TagFromObject(soa, basket.thisPtr);
- }
-
- for (size_t i = 0; i < match_count; i++) {
- expandBufAdd1(pReq, match_list[i]->eventKind);
- expandBufAdd4BE(pReq, match_list[i]->requestId);
- expandBufAdd8BE(pReq, thread_id);
- expandBufAddLocation(pReq, jdwp_location);
- expandBufAdd1(pReq, type_tag);
- expandBufAddRefTypeId(pReq, field_type_id);
- expandBufAddFieldId(pReq, field_id);
- expandBufAdd1(pReq, tag);
- expandBufAddObjectId(pReq, instance_id);
- if (is_modification) {
- Dbg::OutputFieldValue(field_id, fieldValue, pReq);
- }
- }
- }
-
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- CleanupMatchList(match_list, match_count);
- }
+ {
+ MutexLock mu(Thread::Current(), event_list_lock_);
+ CleanupMatchList(match_list);
}
Dbg::ManageDeoptimization();
SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
- return match_count != 0;
}
/*
@@ -1038,7 +1004,7 @@
* Valid mods:
* Count, ThreadOnly
*/
-bool JdwpState::PostThreadChange(Thread* thread, bool start) {
+void JdwpState::PostThreadChange(Thread* thread, bool start) {
CHECK_EQ(thread, Thread::Current());
/*
@@ -1046,61 +1012,45 @@
*/
if (InvokeInProgress()) {
LOG(WARNING) << "Not posting thread change during invoke";
- return false;
+ return;
}
ModBasket basket;
basket.thread = thread;
- ExpandBuf* pReq = NULL;
- JdwpSuspendPolicy suspend_policy = SP_NONE;
- JdwpEvent** match_list = nullptr;
- size_t match_count = 0;
- ObjectId thread_id = 0;
+ std::vector<JdwpEvent*> match_list;
+ const JdwpEventKind match_kind = (start) ? EK_THREAD_START : EK_THREAD_DEATH;
+ if (!FindMatchingEvents(match_kind, basket, &match_list)) {
+ // No matching event.
+ return;
+ }
+
+ JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
+ ObjectId thread_id = Dbg::GetThreadId(basket.thread);
+
+ if (VLOG_IS_ON(jdwp)) {
+ LogMatchingEventsAndThread(match_list, thread_id);
+ VLOG(jdwp) << " suspend_policy=" << suspend_policy;
+ }
+
+ ExpandBuf* pReq = eventPrep();
+ expandBufAdd1(pReq, suspend_policy);
+ expandBufAdd4BE(pReq, match_list.size());
+
+ for (const JdwpEvent* pEvent : match_list) {
+ expandBufAdd1(pReq, pEvent->eventKind);
+ expandBufAdd4BE(pReq, pEvent->requestId);
+ expandBufAdd8BE(pReq, thread_id);
+ }
+
{
- {
- // Don't allow the list to be updated while we scan it.
- MutexLock mu(Thread::Current(), event_list_lock_);
- match_list = AllocMatchList(event_list_size_);
- if (start) {
- FindMatchingEvents(EK_THREAD_START, basket, match_list, &match_count);
- } else {
- FindMatchingEvents(EK_THREAD_DEATH, basket, match_list, &match_count);
- }
- }
-
- if (match_count != 0) {
- suspend_policy = scanSuspendPolicy(match_list, match_count);
-
- thread_id = Dbg::GetThreadId(basket.thread);
-
- if (VLOG_IS_ON(jdwp)) {
- LogMatchingEventsAndThread(match_list, match_count, thread_id);
- VLOG(jdwp) << " suspend_policy=" << suspend_policy;
- }
-
- pReq = eventPrep();
- expandBufAdd1(pReq, suspend_policy);
- expandBufAdd4BE(pReq, match_count);
-
- for (size_t i = 0; i < match_count; i++) {
- expandBufAdd1(pReq, match_list[i]->eventKind);
- expandBufAdd4BE(pReq, match_list[i]->requestId);
- expandBufAdd8BE(pReq, thread_id);
- }
- }
-
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- CleanupMatchList(match_list, match_count);
- }
+ MutexLock mu(Thread::Current(), event_list_lock_);
+ CleanupMatchList(match_list);
}
Dbg::ManageDeoptimization();
SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
-
- return match_count != 0;
}
/*
@@ -1132,7 +1082,7 @@
* because there's a pretty good chance that we're not going to send it
* up the debugger.
*/
-bool JdwpState::PostException(const EventLocation* pThrowLoc, mirror::Throwable* exception_object,
+void JdwpState::PostException(const EventLocation* pThrowLoc, mirror::Throwable* exception_object,
const EventLocation* pCatchLoc, mirror::Object* thisPtr) {
DCHECK(exception_object != nullptr);
DCHECK(pThrowLoc != nullptr);
@@ -1159,72 +1109,61 @@
/* don't try to post an exception caused by the debugger */
if (InvokeInProgress()) {
VLOG(jdwp) << "Not posting exception hit during invoke (" << basket.className << ")";
- return false;
+ return;
}
- size_t match_count = 0;
- ExpandBuf* pReq = NULL;
- JdwpSuspendPolicy suspend_policy = SP_NONE;
- JdwpEvent** match_list = nullptr;
- ObjectId thread_id = 0;
+ std::vector<JdwpEvent*> match_list;
+ if (!FindMatchingEvents(EK_EXCEPTION, basket, &match_list)) {
+ // No matching event.
+ return;
+ }
+
+ JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
+ ObjectId thread_id = Dbg::GetThreadId(basket.thread);
+ ObjectRegistry* registry = Dbg::GetObjectRegistry();
+ ObjectId exceptionId = registry->Add(exception_object);
+ JDWP::JdwpLocation jdwp_throw_location;
+ JDWP::JdwpLocation jdwp_catch_location;
+ SetJdwpLocationFromEventLocation(pThrowLoc, &jdwp_throw_location);
+ SetJdwpLocationFromEventLocation(pCatchLoc, &jdwp_catch_location);
+
+ if (VLOG_IS_ON(jdwp)) {
+ std::string exceptionClassName(PrettyDescriptor(exception_object->GetClass()));
+
+ LogMatchingEventsAndThread(match_list, thread_id);
+ VLOG(jdwp) << " throwLocation=" << jdwp_throw_location;
+ if (jdwp_catch_location.class_id == 0) {
+ VLOG(jdwp) << " catchLocation=uncaught";
+ } else {
+ VLOG(jdwp) << " catchLocation=" << jdwp_catch_location;
+ }
+ VLOG(jdwp) << StringPrintf(" exception=%#" PRIx64, exceptionId) << " "
+ << exceptionClassName;
+ VLOG(jdwp) << " suspend_policy=" << suspend_policy;
+ }
+
+ ExpandBuf* pReq = eventPrep();
+ expandBufAdd1(pReq, suspend_policy);
+ expandBufAdd4BE(pReq, match_list.size());
+
+ for (const JdwpEvent* pEvent : match_list) {
+ expandBufAdd1(pReq, pEvent->eventKind);
+ expandBufAdd4BE(pReq, pEvent->requestId);
+ expandBufAddObjectId(pReq, thread_id);
+ expandBufAddLocation(pReq, jdwp_throw_location);
+ expandBufAdd1(pReq, JT_OBJECT);
+ expandBufAddObjectId(pReq, exceptionId);
+ expandBufAddLocation(pReq, jdwp_catch_location);
+ }
+
{
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- match_list = AllocMatchList(event_list_size_);
- FindMatchingEvents(EK_EXCEPTION, basket, match_list, &match_count);
- }
- if (match_count != 0) {
- suspend_policy = scanSuspendPolicy(match_list, match_count);
-
- thread_id = Dbg::GetThreadId(basket.thread);
- ObjectRegistry* registry = Dbg::GetObjectRegistry();
- ObjectId exceptionId = registry->Add(exception_object);
- JDWP::JdwpLocation jdwp_throw_location;
- JDWP::JdwpLocation jdwp_catch_location;
- SetJdwpLocationFromEventLocation(pThrowLoc, &jdwp_throw_location);
- SetJdwpLocationFromEventLocation(pCatchLoc, &jdwp_catch_location);
-
- if (VLOG_IS_ON(jdwp)) {
- std::string exceptionClassName(PrettyDescriptor(exception_object->GetClass()));
-
- LogMatchingEventsAndThread(match_list, match_count, thread_id);
- VLOG(jdwp) << " throwLocation=" << jdwp_throw_location;
- if (jdwp_catch_location.class_id == 0) {
- VLOG(jdwp) << " catchLocation=uncaught";
- } else {
- VLOG(jdwp) << " catchLocation=" << jdwp_catch_location;
- }
- VLOG(jdwp) << StringPrintf(" exception=%#" PRIx64, exceptionId) << " "
- << exceptionClassName;
- VLOG(jdwp) << " suspend_policy=" << suspend_policy;
- }
-
- pReq = eventPrep();
- expandBufAdd1(pReq, suspend_policy);
- expandBufAdd4BE(pReq, match_count);
-
- for (size_t i = 0; i < match_count; i++) {
- expandBufAdd1(pReq, match_list[i]->eventKind);
- expandBufAdd4BE(pReq, match_list[i]->requestId);
- expandBufAdd8BE(pReq, thread_id);
- expandBufAddLocation(pReq, jdwp_throw_location);
- expandBufAdd1(pReq, JT_OBJECT);
- expandBufAdd8BE(pReq, exceptionId);
- expandBufAddLocation(pReq, jdwp_catch_location);
- }
- }
-
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- CleanupMatchList(match_list, match_count);
- }
+ MutexLock mu(Thread::Current(), event_list_lock_);
+ CleanupMatchList(match_list);
}
Dbg::ManageDeoptimization();
SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
-
- return match_count != 0;
}
/*
@@ -1233,7 +1172,7 @@
* Valid mods:
* Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
*/
-bool JdwpState::PostClassPrepare(mirror::Class* klass) {
+void JdwpState::PostClassPrepare(mirror::Class* klass) {
DCHECK(klass != nullptr);
ModBasket basket;
@@ -1244,80 +1183,69 @@
/* suppress class prep caused by debugger */
if (InvokeInProgress()) {
VLOG(jdwp) << "Not posting class prep caused by invoke (" << basket.className << ")";
- return false;
+ return;
}
- ExpandBuf* pReq = NULL;
- JdwpSuspendPolicy suspend_policy = SP_NONE;
- JdwpEvent** match_list = nullptr;
- size_t match_count = 0;
- ObjectId thread_id = 0;
+ std::vector<JdwpEvent*> match_list;
+ if (!FindMatchingEvents(EK_CLASS_PREPARE, basket, &match_list)) {
+ // No matching event.
+ return;
+ }
+
+ JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
+ ObjectId thread_id = Dbg::GetThreadId(basket.thread);
+ ObjectRegistry* registry = Dbg::GetObjectRegistry();
+ RefTypeId class_id = registry->AddRefType(basket.locationClass);
+
+ // OLD-TODO - we currently always send both "verified" and "prepared" since
+ // debuggers seem to like that. There might be some advantage to honesty,
+ // since the class may not yet be verified.
+ int status = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
+ JDWP::JdwpTypeTag tag = Dbg::GetTypeTag(basket.locationClass);
+ std::string temp;
+ std::string signature(basket.locationClass->GetDescriptor(&temp));
+
+ if (VLOG_IS_ON(jdwp)) {
+ LogMatchingEventsAndThread(match_list, thread_id);
+ VLOG(jdwp) << StringPrintf(" type=%#" PRIx64, class_id) << " " << signature;
+ VLOG(jdwp) << " suspend_policy=" << suspend_policy;
+ }
+
+ if (thread_id == debug_thread_id_) {
+ /*
+ * JDWP says that, for a class prep in the debugger thread, we
+ * should set thread to null and if any threads were supposed
+ * to be suspended then we suspend all other threads.
+ */
+ VLOG(jdwp) << " NOTE: class prepare in debugger thread!";
+ thread_id = 0;
+ if (suspend_policy == SP_EVENT_THREAD) {
+ suspend_policy = SP_ALL;
+ }
+ }
+
+ ExpandBuf* pReq = eventPrep();
+ expandBufAdd1(pReq, suspend_policy);
+ expandBufAdd4BE(pReq, match_list.size());
+
+ for (const JdwpEvent* pEvent : match_list) {
+ expandBufAdd1(pReq, pEvent->eventKind);
+ expandBufAdd4BE(pReq, pEvent->requestId);
+ expandBufAddObjectId(pReq, thread_id);
+ expandBufAdd1(pReq, tag);
+ expandBufAddRefTypeId(pReq, class_id);
+ expandBufAddUtf8String(pReq, signature);
+ expandBufAdd4BE(pReq, status);
+ }
+
{
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- match_list = AllocMatchList(event_list_size_);
- FindMatchingEvents(EK_CLASS_PREPARE, basket, match_list, &match_count);
- }
- if (match_count != 0) {
- suspend_policy = scanSuspendPolicy(match_list, match_count);
-
- thread_id = Dbg::GetThreadId(basket.thread);
- ObjectRegistry* registry = Dbg::GetObjectRegistry();
- RefTypeId class_id = registry->AddRefType(basket.locationClass);
-
- // OLD-TODO - we currently always send both "verified" and "prepared" since
- // debuggers seem to like that. There might be some advantage to honesty,
- // since the class may not yet be verified.
- int status = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
- JDWP::JdwpTypeTag tag = Dbg::GetTypeTag(basket.locationClass);
- std::string temp;
- std::string signature(basket.locationClass->GetDescriptor(&temp));
-
- if (VLOG_IS_ON(jdwp)) {
- LogMatchingEventsAndThread(match_list, match_count, thread_id);
- VLOG(jdwp) << StringPrintf(" type=%#" PRIx64, class_id) << " " << signature;
- VLOG(jdwp) << " suspend_policy=" << suspend_policy;
- }
-
- if (thread_id == debug_thread_id_) {
- /*
- * JDWP says that, for a class prep in the debugger thread, we
- * should set thread to null and if any threads were supposed
- * to be suspended then we suspend all other threads.
- */
- VLOG(jdwp) << " NOTE: class prepare in debugger thread!";
- thread_id = 0;
- if (suspend_policy == SP_EVENT_THREAD) {
- suspend_policy = SP_ALL;
- }
- }
-
- pReq = eventPrep();
- expandBufAdd1(pReq, suspend_policy);
- expandBufAdd4BE(pReq, match_count);
-
- for (size_t i = 0; i < match_count; i++) {
- expandBufAdd1(pReq, match_list[i]->eventKind);
- expandBufAdd4BE(pReq, match_list[i]->requestId);
- expandBufAdd8BE(pReq, thread_id);
- expandBufAdd1(pReq, tag);
- expandBufAdd8BE(pReq, class_id);
- expandBufAddUtf8String(pReq, signature);
- expandBufAdd4BE(pReq, status);
- }
- }
-
- {
- MutexLock mu(Thread::Current(), event_list_lock_);
- CleanupMatchList(match_list, match_count);
- }
+ MutexLock mu(Thread::Current(), event_list_lock_);
+ CleanupMatchList(match_list);
}
Dbg::ManageDeoptimization();
SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
-
- return match_count != 0;
}
/*
@@ -1331,7 +1259,7 @@
uint8_t header[kJDWPHeaderLen + 8];
size_t dataLen = 0;
- CHECK(iov != NULL);
+ CHECK(iov != nullptr);
CHECK_GT(iov_count, 0);
CHECK_LT(iov_count, 10);
@@ -1348,12 +1276,12 @@
/* form the header (JDWP plus DDMS) */
Set4BE(header, sizeof(header) + dataLen);
- Set4BE(header+4, NextRequestSerial());
- Set1(header+8, 0); /* flags */
- Set1(header+9, kJDWPDdmCmdSet);
- Set1(header+10, kJDWPDdmCmd);
- Set4BE(header+11, type);
- Set4BE(header+15, dataLen);
+ Set4BE(header + 4, NextRequestSerial());
+ Set1(header + 8, 0); /* flags */
+ Set1(header + 9, kJDWPDdmCmdSet);
+ Set1(header + 10, kJDWPDdmCmd);
+ Set4BE(header + 11, type);
+ Set4BE(header + 15, dataLen);
wrapiov[0].iov_base = header;
wrapiov[0].iov_len = sizeof(header);
@@ -1364,7 +1292,7 @@
bool safe_to_release_mutator_lock_over_send = !Locks::mutator_lock_->IsExclusiveHeld(self);
if (safe_to_release_mutator_lock_over_send) {
for (size_t i = 0; i < kMutatorLock; ++i) {
- if (self->GetHeldMutex(static_cast<LockLevel>(i)) != NULL) {
+ if (self->GetHeldMutex(static_cast<LockLevel>(i)) != nullptr) {
safe_to_release_mutator_lock_over_send = false;
break;
}