blob: 4e2b0f813c2f60be40ca3e876b4333d8d4f3a313 [file] [log] [blame]
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Elliott Hughes872d4ec2011-10-21 17:07:15 -070016
Elliott Hughes07ed66b2012-12-12 18:34:25 -080017#include "jdwp/jdwp_event.h"
18
19#include <stddef.h> /* for offsetof() */
Elliott Hughes872d4ec2011-10-21 17:07:15 -070020#include <stdlib.h>
21#include <string.h>
Elliott Hughes872d4ec2011-10-21 17:07:15 -070022#include <unistd.h>
23
Elliott Hughes07ed66b2012-12-12 18:34:25 -080024#include "base/logging.h"
Elliott Hughese222ee02012-12-13 14:41:43 -080025#include "base/stringprintf.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080026#include "debugger.h"
27#include "jdwp/jdwp_constants.h"
28#include "jdwp/jdwp_expand_buf.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080029#include "jdwp/jdwp_priv.h"
Ian Rogers693ff612013-02-01 10:56:12 -080030#include "thread-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080031
Elliott Hughes872d4ec2011-10-21 17:07:15 -070032/*
33General notes:
34
35The event add/remove stuff usually happens from the debugger thread,
36in response to requests from the debugger, but can also happen as the
37result of an event in an arbitrary thread (e.g. an event with a "count"
38mod expires). It's important to keep the event list locked when processing
39events.
40
41Event posting can happen from any thread. The JDWP thread will not usually
42post anything but VM start/death, but if a JDWP request causes a class
43to be loaded, the ClassPrepare event will come from the JDWP thread.
44
45
46We can have serialization issues when we post an event to the debugger.
47For example, a thread could send an "I hit a breakpoint and am suspending
48myself" message to the debugger. Before it manages to suspend itself, the
49debugger's response ("not interested, resume thread") arrives and is
50processed. We try to resume a thread that hasn't yet suspended.
51
52This means that, after posting an event to the debugger, we need to wait
53for the event thread to suspend itself (and, potentially, all other threads)
54before processing any additional requests from the debugger. While doing
55so we need to be aware that multiple threads may be hitting breakpoints
56or other events simultaneously, so we either need to wait for all of them
57or serialize the events with each other.
58
59The current mechanism works like this:
60 Event thread:
61 - If I'm going to suspend, grab the "I am posting an event" token. Wait
62 for it if it's not currently available.
63 - Post the event to the debugger.
64 - If appropriate, suspend others and then myself. As part of suspending
65 myself, release the "I am posting" token.
66 JDWP thread:
67 - When an event arrives, see if somebody is posting an event. If so,
68 sleep until we can acquire the "I am posting an event" token. Release
69 it immediately and continue processing -- the event we have already
70 received should not interfere with other events that haven't yet
71 been posted.
72
73Some care must be taken to avoid deadlock:
74
75 - thread A and thread B exit near-simultaneously, and post thread-death
76 events with a "suspend all" clause
77 - thread A gets the event token, thread B sits and waits for it
78 - thread A wants to suspend all other threads, but thread B is waiting
79 for the token and can't be suspended
80
81So we need to mark thread B in such a way that thread A doesn't wait for it.
82
83If we just bracket the "grab event token" call with a change to VMWAIT
84before sleeping, the switch back to RUNNING state when we get the token
85will cause thread B to suspend (remember, thread A's global suspend is
86still in force, even after it releases the token). Suspending while
87holding the event token is very bad, because it prevents the JDWP thread
88from processing incoming messages.
89
90We need to change to VMWAIT state at the *start* of posting an event,
91and stay there until we either finish posting the event or decide to
92put ourselves to sleep. That way we don't interfere with anyone else and
93don't allow anyone else to interfere with us.
94*/
95
96
97#define kJdwpEventCommandSet 64
98#define kJdwpCompositeCommand 100
99
100namespace art {
101
102namespace JDWP {
103
104/*
105 * Stuff to compare against when deciding if a mod matches. Only the
106 * values for mods valid for the event being evaluated will be filled in.
107 * The rest will be zeroed.
108 */
109struct ModBasket {
jeffhao162fd332013-01-08 16:21:01 -0800110 ModBasket() : pLoc(NULL), threadId(0), classId(0), excepClassId(0),
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200111 caught(false), fieldTypeID(0), fieldId(0), thisPtr(0) { }
jeffhao162fd332013-01-08 16:21:01 -0800112
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700113 const JdwpLocation* pLoc; /* LocationOnly */
Elliott Hughesa2155262011-11-16 16:26:58 -0800114 std::string className; /* ClassMatch/ClassExclude */
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700115 ObjectId threadId; /* ThreadOnly */
116 RefTypeId classId; /* ClassOnly */
117 RefTypeId excepClassId; /* ExceptionOnly */
118 bool caught; /* ExceptionOnly */
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200119 RefTypeId fieldTypeID; /* FieldOnly */
120 FieldId fieldId; /* FieldOnly */
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700121 ObjectId thisPtr; /* InstanceOnly */
122 /* nothing for StepOnly -- handled differently */
123};
124
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100125static bool NeedsFullDeoptimization(JdwpEventKind eventKind) {
126 switch (eventKind) {
127 case EK_METHOD_ENTRY:
128 case EK_METHOD_EXIT:
129 case EK_METHOD_EXIT_WITH_RETURN_VALUE:
130 case EK_SINGLE_STEP:
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200131 case EK_FIELD_ACCESS:
132 case EK_FIELD_MODIFICATION:
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100133 return true;
134 default:
135 return false;
136 }
137}
138
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700139/*
140 * Add an event to the list. Ordering is not important.
141 *
142 * If something prevents the event from being registered, e.g. it's a
143 * single-step request on a thread that doesn't exist, the event will
144 * not be added to the list, and an appropriate error will be returned.
145 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800146JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700147 CHECK(pEvent != NULL);
148 CHECK(pEvent->prev == NULL);
149 CHECK(pEvent->next == NULL);
150
151 /*
152 * If one or more "break"-type mods are used, register them with
153 * the interpreter.
154 */
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100155 DeoptimizationRequest req;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700156 for (int i = 0; i < pEvent->modCount; i++) {
157 const JdwpEventMod* pMod = &pEvent->mods[i];
158 if (pMod->modKind == MK_LOCATION_ONLY) {
159 /* should only be for Breakpoint, Step, and Exception */
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100160 Dbg::WatchLocation(&pMod->locationOnly.loc, &req);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700161 } else if (pMod->modKind == MK_STEP) {
162 /* should only be for EK_SINGLE_STEP; should only be one */
163 JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
164 JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
Elliott Hughes2435a572012-02-17 16:07:41 -0800165 JdwpError status = Dbg::ConfigureStep(pMod->step.threadId, size, depth);
166 if (status != ERR_NONE) {
167 return status;
168 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700169 }
170 }
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100171 if (NeedsFullDeoptimization(pEvent->eventKind)) {
172 CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
173 CHECK(req.method == nullptr);
174 req.kind = DeoptimizationRequest::kFullDeoptimization;
175 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700176
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100177 {
178 /*
179 * Add to list.
180 */
181 MutexLock mu(Thread::Current(), event_list_lock_);
182 if (event_list_ != NULL) {
183 pEvent->next = event_list_;
184 event_list_->prev = pEvent;
185 }
186 event_list_ = pEvent;
187 ++event_list_size_;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700188 }
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100189
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100190 // TODO we can do better job here since we should process only one request: the one we just
191 // created.
192 Dbg::RequestDeoptimization(req);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100193 Dbg::ManageDeoptimization();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700194
195 return ERR_NONE;
196}
197
198/*
199 * Remove an event from the list. This will also remove the event from
200 * any optimization tables, e.g. breakpoints.
201 *
202 * Does not free the JdwpEvent.
203 *
204 * Grab the eventLock before calling here.
205 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800206void JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700207 if (pEvent->prev == NULL) {
208 /* head of the list */
Elliott Hughesf8349362012-06-18 15:00:06 -0700209 CHECK(event_list_ == pEvent);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700210
Elliott Hughesf8349362012-06-18 15:00:06 -0700211 event_list_ = pEvent->next;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700212 } else {
213 pEvent->prev->next = pEvent->next;
214 }
215
216 if (pEvent->next != NULL) {
217 pEvent->next->prev = pEvent->prev;
218 pEvent->next = NULL;
219 }
220 pEvent->prev = NULL;
221
222 /*
223 * Unhook us from the interpreter, if necessary.
224 */
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100225 DeoptimizationRequest req;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700226 for (int i = 0; i < pEvent->modCount; i++) {
227 JdwpEventMod* pMod = &pEvent->mods[i];
228 if (pMod->modKind == MK_LOCATION_ONLY) {
229 /* should only be for Breakpoint, Step, and Exception */
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100230 Dbg::UnwatchLocation(&pMod->locationOnly.loc, &req);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700231 }
232 if (pMod->modKind == MK_STEP) {
233 /* should only be for EK_SINGLE_STEP; should only be one */
234 Dbg::UnconfigureStep(pMod->step.threadId);
235 }
236 }
Sebastien Hertz7ec2f1c2014-03-27 20:06:47 +0100237 if (pEvent->eventKind == EK_SINGLE_STEP) {
238 // Special case for single-steps where we want to avoid the slow pattern deoptimize/undeoptimize
239 // loop between each single-step. In a IDE, this would happens each time the user click on the
240 // "single-step" button. Here we delay the full undeoptimization to the next resume
241 // (VM.Resume or ThreadReference.Resume) or the end of the debugging session (VM.Dispose or
242 // runtime shutdown).
243 // Therefore, in a singles-stepping sequence, only the first single-step will trigger a full
244 // deoptimization and only the last single-step will trigger a full undeoptimization.
245 Dbg::DelayFullUndeoptimization();
246 } else if (NeedsFullDeoptimization(pEvent->eventKind)) {
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100247 CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
248 CHECK(req.method == nullptr);
249 req.kind = DeoptimizationRequest::kFullUndeoptimization;
250 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700251
Elliott Hughesf8349362012-06-18 15:00:06 -0700252 --event_list_size_;
253 CHECK(event_list_size_ != 0 || event_list_ == NULL);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100254
Sebastien Hertz4d25df32014-03-21 17:44:46 +0100255 Dbg::RequestDeoptimization(req);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700256}
257
258/*
259 * Remove the event with the given ID from the list.
260 *
261 * Failure to find the event isn't really an error, but it is a little
262 * weird. (It looks like Eclipse will try to be extra careful and will
263 * explicitly remove one-off single-step events.)
264 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800265void JdwpState::UnregisterEventById(uint32_t requestId) {
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100266 bool found = false;
267 {
268 MutexLock mu(Thread::Current(), event_list_lock_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700269
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100270 for (JdwpEvent* pEvent = event_list_; pEvent != nullptr; pEvent = pEvent->next) {
271 if (pEvent->requestId == requestId) {
272 found = true;
273 UnregisterEvent(pEvent);
274 EventFree(pEvent);
275 break; /* there can be only one with a given ID */
276 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700277 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700278 }
279
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100280 if (found) {
281 Dbg::ManageDeoptimization();
282 } else {
Brian Carlstrom4d466a82014-05-08 19:05:29 -0700283 LOG(WARNING) << StringPrintf("Odd: no match when removing event reqId=0x%04x", requestId);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100284 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700285}
286
287/*
288 * Remove all entries from the event list.
289 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800290void JdwpState::UnregisterAll() {
Ian Rogers50b35e22012-10-04 10:09:15 -0700291 MutexLock mu(Thread::Current(), event_list_lock_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700292
Elliott Hughesf8349362012-06-18 15:00:06 -0700293 JdwpEvent* pEvent = event_list_;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700294 while (pEvent != NULL) {
295 JdwpEvent* pNextEvent = pEvent->next;
296
Elliott Hughes761928d2011-11-16 18:33:03 -0800297 UnregisterEvent(pEvent);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700298 EventFree(pEvent);
299 pEvent = pNextEvent;
300 }
301
Elliott Hughesf8349362012-06-18 15:00:06 -0700302 event_list_ = NULL;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700303}
304
305/*
306 * Allocate a JdwpEvent struct with enough space to hold the specified
307 * number of mod records.
308 */
309JdwpEvent* EventAlloc(int numMods) {
310 JdwpEvent* newEvent;
311 int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
312 newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
313 memset(newEvent, 0, allocSize);
314 return newEvent;
315}
316
317/*
318 * Free a JdwpEvent.
319 *
320 * Do not call this until the event has been removed from the list.
321 */
322void EventFree(JdwpEvent* pEvent) {
323 if (pEvent == NULL) {
324 return;
325 }
326
327 /* make sure it was removed from the list */
328 CHECK(pEvent->prev == NULL);
329 CHECK(pEvent->next == NULL);
Elliott Hughesf8349362012-06-18 15:00:06 -0700330 /* want to check state->event_list_ != pEvent */
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700331
332 /*
333 * Free any hairy bits in the mods.
334 */
335 for (int i = 0; i < pEvent->modCount; i++) {
336 if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
337 free(pEvent->mods[i].classMatch.classPattern);
338 pEvent->mods[i].classMatch.classPattern = NULL;
339 }
340 if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
341 free(pEvent->mods[i].classExclude.classPattern);
342 pEvent->mods[i].classExclude.classPattern = NULL;
343 }
344 }
345
346 free(pEvent);
347}
348
349/*
350 * Allocate storage for matching events. To keep things simple we
351 * use an array with enough storage for the entire list.
352 *
353 * The state->eventLock should be held before calling.
354 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800355static JdwpEvent** AllocMatchList(size_t event_count) {
356 return new JdwpEvent*[event_count];
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700357}
358
359/*
360 * Run through the list and remove any entries with an expired "count" mod
361 * from the event list, then free the match list.
362 */
Elliott Hughesf8349362012-06-18 15:00:06 -0700363void JdwpState::CleanupMatchList(JdwpEvent** match_list, int match_count) {
364 JdwpEvent** ppEvent = match_list;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700365
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800366 while (match_count--) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700367 JdwpEvent* pEvent = *ppEvent;
368
369 for (int i = 0; i < pEvent->modCount; i++) {
370 if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800371 VLOG(jdwp) << "##### Removing expired event";
Elliott Hughes761928d2011-11-16 18:33:03 -0800372 UnregisterEvent(pEvent);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700373 EventFree(pEvent);
374 break;
375 }
376 }
377
378 ppEvent++;
379 }
380
Elliott Hughesf8349362012-06-18 15:00:06 -0700381 delete[] match_list;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700382}
383
384/*
385 * Match a string against a "restricted regular expression", which is just
386 * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
387 *
388 * ("Restricted name globbing" might have been a better term.)
389 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800390static bool PatternMatch(const char* pattern, const std::string& target) {
Elliott Hughesa2155262011-11-16 16:26:58 -0800391 size_t patLen = strlen(pattern);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700392 if (pattern[0] == '*') {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700393 patLen--;
Elliott Hughesa2155262011-11-16 16:26:58 -0800394 if (target.size() < patLen) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700395 return false;
396 }
Elliott Hughesa2155262011-11-16 16:26:58 -0800397 return strcmp(pattern+1, target.c_str() + (target.size()-patLen)) == 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700398 } else if (pattern[patLen-1] == '*') {
Elliott Hughesa2155262011-11-16 16:26:58 -0800399 return strncmp(pattern, target.c_str(), patLen-1) == 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700400 } else {
Elliott Hughesa2155262011-11-16 16:26:58 -0800401 return strcmp(pattern, target.c_str()) == 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700402 }
403}
404
405/*
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700406 * See if the event's mods match up with the contents of "basket".
407 *
408 * If we find a Count mod before rejecting an event, we decrement it. We
409 * need to do this even if later mods cause us to ignore the event.
410 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700411static bool ModsMatch(JdwpEvent* pEvent, ModBasket* basket)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700412 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700413 JdwpEventMod* pMod = pEvent->mods;
414
415 for (int i = pEvent->modCount; i > 0; i--, pMod++) {
416 switch (pMod->modKind) {
417 case MK_COUNT:
418 CHECK_GT(pMod->count.count, 0);
419 pMod->count.count--;
Sebastien Hertz43207792014-04-15 16:03:27 +0200420 if (pMod->count.count > 0) {
421 return false;
422 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700423 break;
424 case MK_CONDITIONAL:
425 CHECK(false); // should not be getting these
426 break;
427 case MK_THREAD_ONLY:
428 if (pMod->threadOnly.threadId != basket->threadId) {
429 return false;
430 }
431 break;
432 case MK_CLASS_ONLY:
433 if (!Dbg::MatchType(basket->classId, pMod->classOnly.refTypeId)) {
434 return false;
435 }
436 break;
437 case MK_CLASS_MATCH:
Elliott Hughes761928d2011-11-16 18:33:03 -0800438 if (!PatternMatch(pMod->classMatch.classPattern, basket->className)) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700439 return false;
440 }
441 break;
442 case MK_CLASS_EXCLUDE:
Elliott Hughes761928d2011-11-16 18:33:03 -0800443 if (PatternMatch(pMod->classMatch.classPattern, basket->className)) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700444 return false;
445 }
446 break;
447 case MK_LOCATION_ONLY:
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800448 if (pMod->locationOnly.loc != *basket->pLoc) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700449 return false;
450 }
451 break;
452 case MK_EXCEPTION_ONLY:
453 if (pMod->exceptionOnly.refTypeId != 0 && !Dbg::MatchType(basket->excepClassId, pMod->exceptionOnly.refTypeId)) {
454 return false;
455 }
456 if ((basket->caught && !pMod->exceptionOnly.caught) || (!basket->caught && !pMod->exceptionOnly.uncaught)) {
457 return false;
458 }
459 break;
460 case MK_FIELD_ONLY:
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200461 if (pMod->fieldOnly.fieldId != basket->fieldId) {
462 return false;
463 }
464 if (!Dbg::MatchType(basket->fieldTypeID, pMod->fieldOnly.refTypeId)) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700465 return false;
466 }
467 break;
468 case MK_STEP:
469 if (pMod->step.threadId != basket->threadId) {
470 return false;
471 }
472 break;
473 case MK_INSTANCE_ONLY:
474 if (pMod->instanceOnly.objectId != basket->thisPtr) {
475 return false;
476 }
477 break;
478 default:
Elliott Hughes7b3cdfc2011-12-08 21:28:17 -0800479 LOG(FATAL) << "unknown mod kind " << pMod->modKind;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700480 break;
481 }
482 }
483 return true;
484}
485
486/*
487 * Find all events of type "eventKind" with mods that match up with the
488 * rest of the arguments.
489 *
Elliott Hughesf8349362012-06-18 15:00:06 -0700490 * Found events are appended to "match_list", and "*pMatchCount" is advanced,
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700491 * so this may be called multiple times for grouped events.
492 *
493 * DO NOT call this multiple times for the same eventKind, as Count mods are
494 * decremented during the scan.
495 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700496void JdwpState::FindMatchingEvents(JdwpEventKind eventKind, ModBasket* basket,
497 JdwpEvent** match_list, int* pMatchCount) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700498 /* start after the existing entries */
Elliott Hughesf8349362012-06-18 15:00:06 -0700499 match_list += *pMatchCount;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700500
Elliott Hughesf8349362012-06-18 15:00:06 -0700501 JdwpEvent* pEvent = event_list_;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700502 while (pEvent != NULL) {
Elliott Hughes761928d2011-11-16 18:33:03 -0800503 if (pEvent->eventKind == eventKind && ModsMatch(pEvent, basket)) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700504 *match_list++ = pEvent;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700505 (*pMatchCount)++;
506 }
507
508 pEvent = pEvent->next;
509 }
510}
511
512/*
513 * Scan through the list of matches and determine the most severe
514 * suspension policy.
515 */
Elliott Hughesf8349362012-06-18 15:00:06 -0700516static JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** match_list, int match_count) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700517 JdwpSuspendPolicy policy = SP_NONE;
518
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800519 while (match_count--) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700520 if ((*match_list)->suspend_policy > policy) {
521 policy = (*match_list)->suspend_policy;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700522 }
Elliott Hughesf8349362012-06-18 15:00:06 -0700523 match_list++;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700524 }
525
526 return policy;
527}
528
529/*
530 * Three possibilities:
531 * SP_NONE - do nothing
532 * SP_EVENT_THREAD - suspend ourselves
533 * SP_ALL - suspend everybody except JDWP support thread
534 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700535void JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspend_policy, JDWP::ObjectId thread_self_id) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700536 VLOG(jdwp) << "SuspendByPolicy(" << suspend_policy << ")";
537 if (suspend_policy == SP_NONE) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700538 return;
539 }
540
Elliott Hughesf8349362012-06-18 15:00:06 -0700541 if (suspend_policy == SP_ALL) {
Elliott Hughes475fc232011-10-25 15:00:35 -0700542 Dbg::SuspendVM();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700543 } else {
Elliott Hughesf8349362012-06-18 15:00:06 -0700544 CHECK_EQ(suspend_policy, SP_EVENT_THREAD);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700545 }
546
547 /* this is rare but possible -- see CLASS_PREPARE handling */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700548 if (thread_self_id == debug_thread_id_) {
Elliott Hughes761928d2011-11-16 18:33:03 -0800549 LOG(INFO) << "NOTE: SuspendByPolicy not suspending JDWP thread";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700550 return;
551 }
552
553 DebugInvokeReq* pReq = Dbg::GetInvokeReq();
554 while (true) {
555 pReq->ready = true;
556 Dbg::SuspendSelf();
557 pReq->ready = false;
558
559 /*
560 * The JDWP thread has told us (and possibly all other threads) to
561 * resume. See if it has left anything in our DebugInvokeReq mailbox.
562 */
Sebastien Hertzd38667a2013-11-25 15:43:54 +0100563 if (!pReq->invoke_needed) {
Elliott Hughes761928d2011-11-16 18:33:03 -0800564 /*LOGD("SuspendByPolicy: no invoke needed");*/
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700565 break;
566 }
567
568 /* grab this before posting/suspending again */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700569 SetWaitForEventThread(thread_self_id);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700570
Elliott Hughesd07986f2011-12-06 18:27:45 -0800571 /* leave pReq->invoke_needed_ raised so we can check reentrancy */
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700572 Dbg::ExecuteMethod(pReq);
573
Elliott Hughes475fc232011-10-25 15:00:35 -0700574 pReq->error = ERR_NONE;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700575 }
576}
577
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700578void JdwpState::SendRequestAndPossiblySuspend(ExpandBuf* pReq, JdwpSuspendPolicy suspend_policy,
579 ObjectId threadId) {
580 Thread* self = Thread::Current();
581 self->AssertThreadSuspensionIsAllowable();
582 /* send request and possibly suspend ourselves */
583 if (pReq != NULL) {
584 JDWP::ObjectId thread_self_id = Dbg::GetThreadSelfId();
585 self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
586 if (suspend_policy != SP_NONE) {
587 SetWaitForEventThread(threadId);
588 }
589 EventFinish(pReq);
590 SuspendByPolicy(suspend_policy, thread_self_id);
591 self->TransitionFromSuspendedToRunnable();
592 }
593}
594
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700595/*
596 * Determine if there is a method invocation in progress in the current
597 * thread.
598 *
Elliott Hughes475fc232011-10-25 15:00:35 -0700599 * We look at the "invoke_needed" flag in the per-thread DebugInvokeReq
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700600 * state. If set, we're in the process of invoking a method.
601 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800602bool JdwpState::InvokeInProgress() {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700603 DebugInvokeReq* pReq = Dbg::GetInvokeReq();
Sebastien Hertzd38667a2013-11-25 15:43:54 +0100604 return pReq->invoke_needed;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700605}
606
607/*
608 * We need the JDWP thread to hold off on doing stuff while we post an
609 * event and then suspend ourselves.
610 *
611 * Call this with a threadId of zero if you just want to wait for the
612 * current thread operation to complete.
613 *
614 * This could go to sleep waiting for another thread, so it's important
615 * that the thread be marked as VMWAIT before calling here.
616 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700617void JdwpState::SetWaitForEventThread(ObjectId threadId) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700618 bool waited = false;
619
620 /* this is held for very brief periods; contention is unlikely */
Ian Rogers81d425b2012-09-27 16:03:43 -0700621 Thread* self = Thread::Current();
622 MutexLock mu(self, event_thread_lock_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700623
624 /*
625 * If another thread is already doing stuff, wait for it. This can
626 * go to sleep indefinitely.
627 */
Elliott Hughesa21039c2012-06-21 12:09:25 -0700628 while (event_thread_id_ != 0) {
Ian Rogersd9e4e0c2014-01-23 20:11:40 -0800629 VLOG(jdwp) << StringPrintf("event in progress (%#" PRIx64 "), %#" PRIx64 " sleeping",
630 event_thread_id_, threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700631 waited = true;
Ian Rogersc604d732012-10-14 16:09:54 -0700632 event_thread_cond_.Wait(self);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700633 }
634
635 if (waited || threadId != 0) {
Ian Rogersd9e4e0c2014-01-23 20:11:40 -0800636 VLOG(jdwp) << StringPrintf("event token grabbed (%#" PRIx64 ")", threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700637 }
638 if (threadId != 0) {
Elliott Hughesa21039c2012-06-21 12:09:25 -0700639 event_thread_id_ = threadId;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700640 }
641}
642
643/*
644 * Clear the threadId and signal anybody waiting.
645 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700646void JdwpState::ClearWaitForEventThread() {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700647 /*
648 * Grab the mutex. Don't try to go in/out of VMWAIT mode, as this
649 * function is called by dvmSuspendSelf(), and the transition back
650 * to RUNNING would confuse it.
651 */
Ian Rogersc604d732012-10-14 16:09:54 -0700652 Thread* self = Thread::Current();
653 MutexLock mu(self, event_thread_lock_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700654
Elliott Hughesa21039c2012-06-21 12:09:25 -0700655 CHECK_NE(event_thread_id_, 0U);
Ian Rogersd9e4e0c2014-01-23 20:11:40 -0800656 VLOG(jdwp) << StringPrintf("cleared event token (%#" PRIx64 ")", event_thread_id_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700657
Elliott Hughesa21039c2012-06-21 12:09:25 -0700658 event_thread_id_ = 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700659
Ian Rogersc604d732012-10-14 16:09:54 -0700660 event_thread_cond_.Signal(self);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700661}
662
663
664/*
665 * Prep an event. Allocates storage for the message and leaves space for
666 * the header.
667 */
668static ExpandBuf* eventPrep() {
669 ExpandBuf* pReq = expandBufAlloc();
670 expandBufAddSpace(pReq, kJDWPHeaderLen);
671 return pReq;
672}
673
674/*
675 * Write the header into the buffer and send the packet off to the debugger.
676 *
677 * Takes ownership of "pReq" (currently discards it).
678 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800679void JdwpState::EventFinish(ExpandBuf* pReq) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700680 uint8_t* buf = expandBufGetBuffer(pReq);
681
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700682 Set4BE(buf, expandBufGetLength(pReq));
Elliott Hughes761928d2011-11-16 18:33:03 -0800683 Set4BE(buf+4, NextRequestSerial());
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700684 Set1(buf+8, 0); /* flags */
685 Set1(buf+9, kJdwpEventCommandSet);
686 Set1(buf+10, kJdwpCompositeCommand);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700687
Sebastien Hertz99660e12014-02-19 15:04:42 +0100688 // Prevents from interleaving commands and events. Otherwise we could end up in sending an event
689 // before sending the reply of the command being processed and would lead to bad synchronization
690 // between the debugger and the debuggee.
691 WaitForProcessingRequest();
692
Elliott Hughes761928d2011-11-16 18:33:03 -0800693 SendRequest(pReq);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700694
695 expandBufFree(pReq);
696}
697
698
699/*
700 * Tell the debugger that we have finished initializing. This is always
701 * sent, even if the debugger hasn't requested it.
702 *
703 * This should be sent "before the main thread is started and before
704 * any application code has been executed". The thread ID in the message
705 * must be for the main thread.
706 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700707bool JdwpState::PostVMStart() {
Elliott Hughesf8349362012-06-18 15:00:06 -0700708 JdwpSuspendPolicy suspend_policy;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700709 ObjectId threadId = Dbg::GetThreadSelfId();
710
Elliott Hughes376a7a02011-10-24 18:35:55 -0700711 if (options_->suspend) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700712 suspend_policy = SP_ALL;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700713 } else {
Elliott Hughesf8349362012-06-18 15:00:06 -0700714 suspend_policy = SP_NONE;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700715 }
716
Elliott Hughes761928d2011-11-16 18:33:03 -0800717 ExpandBuf* pReq = eventPrep();
718 {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700719 MutexLock mu(Thread::Current(), event_list_lock_); // probably don't need this here
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700720
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800721 VLOG(jdwp) << "EVENT: " << EK_VM_START;
Elliott Hughesf8349362012-06-18 15:00:06 -0700722 VLOG(jdwp) << " suspend_policy=" << suspend_policy;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700723
Elliott Hughesf8349362012-06-18 15:00:06 -0700724 expandBufAdd1(pReq, suspend_policy);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700725 expandBufAdd4BE(pReq, 1);
726
727 expandBufAdd1(pReq, EK_VM_START);
728 expandBufAdd4BE(pReq, 0); /* requestId */
729 expandBufAdd8BE(pReq, threadId);
730 }
731
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100732 Dbg::ManageDeoptimization();
733
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700734 /* send request and possibly suspend ourselves */
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700735 SendRequestAndPossiblySuspend(pReq, suspend_policy, threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700736
737 return true;
738}
739
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700740/*
741 * A location of interest has been reached. This handles:
742 * Breakpoint
743 * SingleStep
744 * MethodEntry
745 * MethodExit
746 * These four types must be grouped together in a single response. The
747 * "eventFlags" indicates the type of event(s) that have happened.
748 *
749 * Valid mods:
750 * Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
751 * LocationOnly (for breakpoint/step only)
752 * Step (for step only)
753 *
754 * Interesting test cases:
755 * - Put a breakpoint on a native method. Eclipse creates METHOD_ENTRY
756 * and METHOD_EXIT events with a ClassOnly mod on the method's class.
757 * - Use "run to line". Eclipse creates a BREAKPOINT with Count=1.
758 * - Single-step to a line with a breakpoint. Should get a single
759 * event message with both events in it.
760 */
Jeff Hao579b0242013-11-18 13:16:49 -0800761bool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags,
762 const JValue* returnValue) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700763 ModBasket basket;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700764 basket.pLoc = pLoc;
Elliott Hughes74847412012-06-20 18:10:21 -0700765 basket.classId = pLoc->class_id;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700766 basket.thisPtr = thisPtr;
767 basket.threadId = Dbg::GetThreadSelfId();
Elliott Hughes74847412012-06-20 18:10:21 -0700768 basket.className = Dbg::GetClassName(pLoc->class_id);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700769
770 /*
771 * On rare occasions we may need to execute interpreted code in the VM
772 * while handling a request from the debugger. Don't fire breakpoints
773 * while doing so. (I don't think we currently do this at all, so
774 * this is mostly paranoia.)
775 */
Elliott Hughesa21039c2012-06-21 12:09:25 -0700776 if (basket.threadId == debug_thread_id_) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800777 VLOG(jdwp) << "Ignoring location event in JDWP thread";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700778 return false;
779 }
780
781 /*
782 * The debugger variable display tab may invoke the interpreter to format
783 * complex objects. We want to ignore breakpoints and method entry/exit
784 * traps while working on behalf of the debugger.
785 *
786 * If we don't ignore them, the VM will get hung up, because we'll
787 * suspend on a breakpoint while the debugger is still waiting for its
788 * method invocation to complete.
789 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800790 if (InvokeInProgress()) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800791 VLOG(jdwp) << "Not checking breakpoints during invoke (" << basket.className << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700792 return false;
793 }
794
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800795 int match_count = 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700796 ExpandBuf* pReq = NULL;
Elliott Hughesf8349362012-06-18 15:00:06 -0700797 JdwpSuspendPolicy suspend_policy = SP_NONE;
Elliott Hughes761928d2011-11-16 18:33:03 -0800798 {
Ian Rogers50b35e22012-10-04 10:09:15 -0700799 MutexLock mu(Thread::Current(), event_list_lock_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100800 JdwpEvent** match_list = AllocMatchList(event_list_size_);
Elliott Hughes86964332012-02-15 19:37:42 -0800801 if ((eventFlags & Dbg::kBreakpoint) != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700802 FindMatchingEvents(EK_BREAKPOINT, &basket, match_list, &match_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700803 }
Elliott Hughes761928d2011-11-16 18:33:03 -0800804 if ((eventFlags & Dbg::kSingleStep) != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700805 FindMatchingEvents(EK_SINGLE_STEP, &basket, match_list, &match_count);
Elliott Hughes761928d2011-11-16 18:33:03 -0800806 }
807 if ((eventFlags & Dbg::kMethodEntry) != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700808 FindMatchingEvents(EK_METHOD_ENTRY, &basket, match_list, &match_count);
Elliott Hughes761928d2011-11-16 18:33:03 -0800809 }
810 if ((eventFlags & Dbg::kMethodExit) != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700811 FindMatchingEvents(EK_METHOD_EXIT, &basket, match_list, &match_count);
Jeff Hao579b0242013-11-18 13:16:49 -0800812 FindMatchingEvents(EK_METHOD_EXIT_WITH_RETURN_VALUE, &basket, match_list, &match_count);
Elliott Hughes761928d2011-11-16 18:33:03 -0800813 }
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800814 if (match_count != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700815 VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
Elliott Hughesa96836a2013-01-17 12:27:49 -0800816 << basket.className << "." << Dbg::GetMethodName(pLoc->method_id)
Ian Rogersd9e4e0c2014-01-23 20:11:40 -0800817 << StringPrintf(" thread=%#" PRIx64 " dex_pc=%#" PRIx64 ")",
818 basket.threadId, pLoc->dex_pc);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700819
Elliott Hughesf8349362012-06-18 15:00:06 -0700820 suspend_policy = scanSuspendPolicy(match_list, match_count);
821 VLOG(jdwp) << " suspend_policy=" << suspend_policy;
Elliott Hughes761928d2011-11-16 18:33:03 -0800822
823 pReq = eventPrep();
Elliott Hughesf8349362012-06-18 15:00:06 -0700824 expandBufAdd1(pReq, suspend_policy);
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800825 expandBufAdd4BE(pReq, match_count);
Elliott Hughes761928d2011-11-16 18:33:03 -0800826
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800827 for (int i = 0; i < match_count; i++) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700828 expandBufAdd1(pReq, match_list[i]->eventKind);
829 expandBufAdd4BE(pReq, match_list[i]->requestId);
Elliott Hughes761928d2011-11-16 18:33:03 -0800830 expandBufAdd8BE(pReq, basket.threadId);
Elliott Hughes6e9d22c2012-06-22 15:02:37 -0700831 expandBufAddLocation(pReq, *pLoc);
Jeff Hao579b0242013-11-18 13:16:49 -0800832 if (match_list[i]->eventKind == EK_METHOD_EXIT_WITH_RETURN_VALUE) {
833 Dbg::OutputMethodReturnValue(pLoc->method_id, returnValue, pReq);
834 }
Elliott Hughes761928d2011-11-16 18:33:03 -0800835 }
836 }
837
Elliott Hughesf8349362012-06-18 15:00:06 -0700838 CleanupMatchList(match_list, match_count);
Elliott Hughes761928d2011-11-16 18:33:03 -0800839 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700840
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100841 Dbg::ManageDeoptimization();
842
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700843 SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800844 return match_count != 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700845}
846
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200847bool JdwpState::PostFieldEvent(const JdwpLocation* pLoc, RefTypeId typeId, FieldId fieldId,
848 ObjectId thisPtr, const JValue* fieldValue, bool is_modification) {
849 ModBasket basket;
850 basket.pLoc = pLoc;
851 basket.classId = pLoc->class_id;
852 basket.thisPtr = thisPtr;
853 basket.threadId = Dbg::GetThreadSelfId();
854 basket.className = Dbg::GetClassName(pLoc->class_id);
Sebastien Hertz479fc1e2014-04-04 17:51:34 +0200855 basket.fieldTypeID = typeId;
856 basket.fieldId = fieldId;
Sebastien Hertz3f52eaf2014-04-04 17:50:18 +0200857
858 if (InvokeInProgress()) {
859 VLOG(jdwp) << "Not posting field event during invoke";
860 return false;
861 }
862
863 // Get field's reference type tag.
864 JDWP::JdwpTypeTag type_tag;
865 uint32_t class_status; // unused here.
866 JdwpError error = Dbg::GetClassInfo(typeId, &type_tag, &class_status, NULL);
867 if (error != ERR_NONE) {
868 return false;
869 }
870
871 // Get instance type tag.
872 uint8_t tag;
873 error = Dbg::GetObjectTag(thisPtr, tag);
874 if (error != ERR_NONE) {
875 return false;
876 }
877
878 int match_count = 0;
879 ExpandBuf* pReq = NULL;
880 JdwpSuspendPolicy suspend_policy = SP_NONE;
881 {
882 MutexLock mu(Thread::Current(), event_list_lock_);
883 JdwpEvent** match_list = AllocMatchList(event_list_size_);
884
885 if (is_modification) {
886 FindMatchingEvents(EK_FIELD_MODIFICATION, &basket, match_list, &match_count);
887 } else {
888 FindMatchingEvents(EK_FIELD_ACCESS, &basket, match_list, &match_count);
889 }
890 if (match_count != 0) {
891 VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
892 << basket.className << "." << Dbg::GetMethodName(pLoc->method_id)
893 << StringPrintf(" thread=%#" PRIx64 " dex_pc=%#" PRIx64 ")",
894 basket.threadId, pLoc->dex_pc);
895
896 suspend_policy = scanSuspendPolicy(match_list, match_count);
897 VLOG(jdwp) << " suspend_policy=" << suspend_policy;
898
899 pReq = eventPrep();
900 expandBufAdd1(pReq, suspend_policy);
901 expandBufAdd4BE(pReq, match_count);
902
903 for (int i = 0; i < match_count; i++) {
904 expandBufAdd1(pReq, match_list[i]->eventKind);
905 expandBufAdd4BE(pReq, match_list[i]->requestId);
906 expandBufAdd8BE(pReq, basket.threadId);
907 expandBufAddLocation(pReq, *pLoc);
908 expandBufAdd1(pReq, type_tag);
909 expandBufAddRefTypeId(pReq, typeId);
910 expandBufAddFieldId(pReq, fieldId);
911 expandBufAdd1(pReq, tag);
912 expandBufAddObjectId(pReq, thisPtr);
913 if (is_modification) {
914 Dbg::OutputFieldValue(fieldId, fieldValue, pReq);
915 }
916 }
917 }
918
919 CleanupMatchList(match_list, match_count);
920 }
921
922 Dbg::ManageDeoptimization();
923
924 SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
925 return match_count != 0;
926}
927
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700928/*
929 * A thread is starting or stopping.
930 *
931 * Valid mods:
932 * Count, ThreadOnly
933 */
Elliott Hughes234ab152011-10-26 14:02:26 -0700934bool JdwpState::PostThreadChange(ObjectId threadId, bool start) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700935 CHECK_EQ(threadId, Dbg::GetThreadSelfId());
936
937 /*
938 * I don't think this can happen.
939 */
Elliott Hughes761928d2011-11-16 18:33:03 -0800940 if (InvokeInProgress()) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700941 LOG(WARNING) << "Not posting thread change during invoke";
942 return false;
943 }
944
945 ModBasket basket;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700946 basket.threadId = threadId;
947
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700948 ExpandBuf* pReq = NULL;
Elliott Hughesf8349362012-06-18 15:00:06 -0700949 JdwpSuspendPolicy suspend_policy = SP_NONE;
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800950 int match_count = 0;
Elliott Hughes234ab152011-10-26 14:02:26 -0700951 {
952 // Don't allow the list to be updated while we scan it.
Ian Rogers50b35e22012-10-04 10:09:15 -0700953 MutexLock mu(Thread::Current(), event_list_lock_);
Elliott Hughesf8349362012-06-18 15:00:06 -0700954 JdwpEvent** match_list = AllocMatchList(event_list_size_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700955
Elliott Hughes234ab152011-10-26 14:02:26 -0700956 if (start) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700957 FindMatchingEvents(EK_THREAD_START, &basket, match_list, &match_count);
Elliott Hughes234ab152011-10-26 14:02:26 -0700958 } else {
Elliott Hughesf8349362012-06-18 15:00:06 -0700959 FindMatchingEvents(EK_THREAD_DEATH, &basket, match_list, &match_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700960 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700961
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800962 if (match_count != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700963 VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
Ian Rogersd9e4e0c2014-01-23 20:11:40 -0800964 << StringPrintf("thread=%#" PRIx64, basket.threadId) << ")";
Elliott Hughes234ab152011-10-26 14:02:26 -0700965
Elliott Hughesf8349362012-06-18 15:00:06 -0700966 suspend_policy = scanSuspendPolicy(match_list, match_count);
967 VLOG(jdwp) << " suspend_policy=" << suspend_policy;
Elliott Hughes234ab152011-10-26 14:02:26 -0700968
969 pReq = eventPrep();
Elliott Hughesf8349362012-06-18 15:00:06 -0700970 expandBufAdd1(pReq, suspend_policy);
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800971 expandBufAdd4BE(pReq, match_count);
Elliott Hughes234ab152011-10-26 14:02:26 -0700972
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800973 for (int i = 0; i < match_count; i++) {
Elliott Hughesf8349362012-06-18 15:00:06 -0700974 expandBufAdd1(pReq, match_list[i]->eventKind);
975 expandBufAdd4BE(pReq, match_list[i]->requestId);
Elliott Hughes234ab152011-10-26 14:02:26 -0700976 expandBufAdd8BE(pReq, basket.threadId);
977 }
978 }
979
Elliott Hughesf8349362012-06-18 15:00:06 -0700980 CleanupMatchList(match_list, match_count);
Elliott Hughes234ab152011-10-26 14:02:26 -0700981 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700982
Sebastien Hertz138dbfc2013-12-04 18:15:25 +0100983 Dbg::ManageDeoptimization();
984
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700985 SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700986
Elliott Hughes2aa2e392012-02-17 17:15:43 -0800987 return match_count != 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700988}
989
990/*
991 * Send a polite "VM is dying" message to the debugger.
992 *
993 * Skips the usual "event token" stuff.
994 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700995bool JdwpState::PostVMDeath() {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -0800996 VLOG(jdwp) << "EVENT: " << EK_VM_DEATH;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700997
998 ExpandBuf* pReq = eventPrep();
999 expandBufAdd1(pReq, SP_NONE);
1000 expandBufAdd4BE(pReq, 1);
1001
1002 expandBufAdd1(pReq, EK_VM_DEATH);
1003 expandBufAdd4BE(pReq, 0);
Elliott Hughes761928d2011-11-16 18:33:03 -08001004 EventFinish(pReq);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001005 return true;
1006}
1007
1008/*
1009 * An exception has been thrown. It may or may not have been caught.
1010 *
1011 * Valid mods:
1012 * Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
1013 * ExceptionOnly, InstanceOnly
1014 *
1015 * The "exceptionId" has not been added to the GC-visible object registry,
1016 * because there's a pretty good chance that we're not going to send it
1017 * up the debugger.
1018 */
Elliott Hughes761928d2011-11-16 18:33:03 -08001019bool JdwpState::PostException(const JdwpLocation* pThrowLoc,
Elliott Hughes74847412012-06-20 18:10:21 -07001020 ObjectId exceptionId, RefTypeId exceptionClassId,
1021 const JdwpLocation* pCatchLoc, ObjectId thisPtr) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001022 ModBasket basket;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001023
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001024 basket.pLoc = pThrowLoc;
Elliott Hughes74847412012-06-20 18:10:21 -07001025 basket.classId = pThrowLoc->class_id;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001026 basket.threadId = Dbg::GetThreadSelfId();
Elliott Hughesc308a5d2012-02-16 17:12:06 -08001027 basket.className = Dbg::GetClassName(basket.classId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001028 basket.excepClassId = exceptionClassId;
Elliott Hughes74847412012-06-20 18:10:21 -07001029 basket.caught = (pCatchLoc->class_id != 0);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001030 basket.thisPtr = thisPtr;
1031
1032 /* don't try to post an exception caused by the debugger */
Elliott Hughes761928d2011-11-16 18:33:03 -08001033 if (InvokeInProgress()) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -08001034 VLOG(jdwp) << "Not posting exception hit during invoke (" << basket.className << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001035 return false;
1036 }
1037
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001038 int match_count = 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001039 ExpandBuf* pReq = NULL;
Elliott Hughesf8349362012-06-18 15:00:06 -07001040 JdwpSuspendPolicy suspend_policy = SP_NONE;
Elliott Hughes761928d2011-11-16 18:33:03 -08001041 {
Ian Rogers50b35e22012-10-04 10:09:15 -07001042 MutexLock mu(Thread::Current(), event_list_lock_);
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001043 JdwpEvent** match_list = AllocMatchList(event_list_size_);
Elliott Hughesf8349362012-06-18 15:00:06 -07001044 FindMatchingEvents(EK_EXCEPTION, &basket, match_list, &match_count);
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001045 if (match_count != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -07001046 VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total)"
Ian Rogersd9e4e0c2014-01-23 20:11:40 -08001047 << StringPrintf(" thread=%#" PRIx64, basket.threadId)
1048 << StringPrintf(" exceptId=%#" PRIx64, exceptionId)
Elliott Hughes436e3722012-02-17 20:01:47 -08001049 << " caught=" << basket.caught << ")"
1050 << " throw: " << *pThrowLoc;
Elliott Hughes74847412012-06-20 18:10:21 -07001051 if (pCatchLoc->class_id == 0) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -08001052 VLOG(jdwp) << " catch: (not caught)";
Elliott Hughes761928d2011-11-16 18:33:03 -08001053 } else {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -08001054 VLOG(jdwp) << " catch: " << *pCatchLoc;
Elliott Hughes761928d2011-11-16 18:33:03 -08001055 }
1056
Elliott Hughesf8349362012-06-18 15:00:06 -07001057 suspend_policy = scanSuspendPolicy(match_list, match_count);
1058 VLOG(jdwp) << " suspend_policy=" << suspend_policy;
Elliott Hughes761928d2011-11-16 18:33:03 -08001059
1060 pReq = eventPrep();
Elliott Hughesf8349362012-06-18 15:00:06 -07001061 expandBufAdd1(pReq, suspend_policy);
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001062 expandBufAdd4BE(pReq, match_count);
Elliott Hughes761928d2011-11-16 18:33:03 -08001063
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001064 for (int i = 0; i < match_count; i++) {
Elliott Hughesf8349362012-06-18 15:00:06 -07001065 expandBufAdd1(pReq, match_list[i]->eventKind);
1066 expandBufAdd4BE(pReq, match_list[i]->requestId);
Elliott Hughes761928d2011-11-16 18:33:03 -08001067 expandBufAdd8BE(pReq, basket.threadId);
1068
Elliott Hughes6e9d22c2012-06-22 15:02:37 -07001069 expandBufAddLocation(pReq, *pThrowLoc);
Elliott Hughes761928d2011-11-16 18:33:03 -08001070 expandBufAdd1(pReq, JT_OBJECT);
1071 expandBufAdd8BE(pReq, exceptionId);
Elliott Hughes6e9d22c2012-06-22 15:02:37 -07001072 expandBufAddLocation(pReq, *pCatchLoc);
Elliott Hughes761928d2011-11-16 18:33:03 -08001073 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001074 }
1075
Elliott Hughesf8349362012-06-18 15:00:06 -07001076 CleanupMatchList(match_list, match_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001077 }
1078
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001079 Dbg::ManageDeoptimization();
1080
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001081 SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001082
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001083 return match_count != 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001084}
1085
1086/*
1087 * Announce that a class has been loaded.
1088 *
1089 * Valid mods:
1090 * Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
1091 */
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001092bool JdwpState::PostClassPrepare(JdwpTypeTag tag, RefTypeId refTypeId, const std::string& signature,
1093 int status) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001094 ModBasket basket;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001095
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001096 basket.classId = refTypeId;
1097 basket.threadId = Dbg::GetThreadSelfId();
Elliott Hughesc308a5d2012-02-16 17:12:06 -08001098 basket.className = Dbg::GetClassName(basket.classId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001099
1100 /* suppress class prep caused by debugger */
Elliott Hughes761928d2011-11-16 18:33:03 -08001101 if (InvokeInProgress()) {
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -08001102 VLOG(jdwp) << "Not posting class prep caused by invoke (" << basket.className << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001103 return false;
1104 }
1105
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001106 ExpandBuf* pReq = NULL;
Elliott Hughesf8349362012-06-18 15:00:06 -07001107 JdwpSuspendPolicy suspend_policy = SP_NONE;
1108 int match_count = 0;
Elliott Hughes761928d2011-11-16 18:33:03 -08001109 {
Ian Rogers50b35e22012-10-04 10:09:15 -07001110 MutexLock mu(Thread::Current(), event_list_lock_);
Elliott Hughesf8349362012-06-18 15:00:06 -07001111 JdwpEvent** match_list = AllocMatchList(event_list_size_);
1112 FindMatchingEvents(EK_CLASS_PREPARE, &basket, match_list, &match_count);
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001113 if (match_count != 0) {
Elliott Hughesf8349362012-06-18 15:00:06 -07001114 VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
Ian Rogersd9e4e0c2014-01-23 20:11:40 -08001115 << StringPrintf("thread=%#" PRIx64, basket.threadId) << ") " << signature;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001116
Elliott Hughesf8349362012-06-18 15:00:06 -07001117 suspend_policy = scanSuspendPolicy(match_list, match_count);
1118 VLOG(jdwp) << " suspend_policy=" << suspend_policy;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001119
Elliott Hughesa21039c2012-06-21 12:09:25 -07001120 if (basket.threadId == debug_thread_id_) {
Elliott Hughes761928d2011-11-16 18:33:03 -08001121 /*
1122 * JDWP says that, for a class prep in the debugger thread, we
1123 * should set threadId to null and if any threads were supposed
1124 * to be suspended then we suspend all other threads.
1125 */
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -08001126 VLOG(jdwp) << " NOTE: class prepare in debugger thread!";
Elliott Hughes761928d2011-11-16 18:33:03 -08001127 basket.threadId = 0;
Elliott Hughesf8349362012-06-18 15:00:06 -07001128 if (suspend_policy == SP_EVENT_THREAD) {
1129 suspend_policy = SP_ALL;
Elliott Hughes761928d2011-11-16 18:33:03 -08001130 }
1131 }
1132
1133 pReq = eventPrep();
Elliott Hughesf8349362012-06-18 15:00:06 -07001134 expandBufAdd1(pReq, suspend_policy);
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001135 expandBufAdd4BE(pReq, match_count);
Elliott Hughes761928d2011-11-16 18:33:03 -08001136
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001137 for (int i = 0; i < match_count; i++) {
Elliott Hughesf8349362012-06-18 15:00:06 -07001138 expandBufAdd1(pReq, match_list[i]->eventKind);
1139 expandBufAdd4BE(pReq, match_list[i]->requestId);
Elliott Hughes761928d2011-11-16 18:33:03 -08001140 expandBufAdd8BE(pReq, basket.threadId);
1141
1142 expandBufAdd1(pReq, tag);
1143 expandBufAdd8BE(pReq, refTypeId);
1144 expandBufAddUtf8String(pReq, signature);
1145 expandBufAdd4BE(pReq, status);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001146 }
1147 }
Elliott Hughesf8349362012-06-18 15:00:06 -07001148 CleanupMatchList(match_list, match_count);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001149 }
1150
Sebastien Hertz138dbfc2013-12-04 18:15:25 +01001151 Dbg::ManageDeoptimization();
1152
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001153 SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001154
Elliott Hughes2aa2e392012-02-17 17:15:43 -08001155 return match_count != 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001156}
1157
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001158/*
1159 * Send up a chunk of DDM data.
1160 *
1161 * While this takes the form of a JDWP "event", it doesn't interact with
1162 * other debugger traffic, and can't suspend the VM, so we skip all of
1163 * the fun event token gymnastics.
1164 */
Elliott Hughescccd84f2011-12-05 16:51:54 -08001165void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001166 uint8_t header[kJDWPHeaderLen + 8];
1167 size_t dataLen = 0;
1168
1169 CHECK(iov != NULL);
Elliott Hughescccd84f2011-12-05 16:51:54 -08001170 CHECK_GT(iov_count, 0);
1171 CHECK_LT(iov_count, 10);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001172
1173 /*
1174 * "Wrap" the contents of the iovec with a JDWP/DDMS header. We do
1175 * this by creating a new copy of the vector with space for the header.
1176 */
Brian Carlstromf5293522013-07-19 00:24:00 -07001177 std::vector<iovec> wrapiov;
1178 wrapiov.push_back(iovec());
Elliott Hughescccd84f2011-12-05 16:51:54 -08001179 for (int i = 0; i < iov_count; i++) {
Brian Carlstromf5293522013-07-19 00:24:00 -07001180 wrapiov.push_back(iov[i]);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001181 dataLen += iov[i].iov_len;
1182 }
1183
1184 /* form the header (JDWP plus DDMS) */
Elliott Hughesf7c3b662011-10-27 12:04:56 -07001185 Set4BE(header, sizeof(header) + dataLen);
1186 Set4BE(header+4, NextRequestSerial());
1187 Set1(header+8, 0); /* flags */
1188 Set1(header+9, kJDWPDdmCmdSet);
1189 Set1(header+10, kJDWPDdmCmd);
1190 Set4BE(header+11, type);
1191 Set4BE(header+15, dataLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001192
1193 wrapiov[0].iov_base = header;
1194 wrapiov[0].iov_len = sizeof(header);
1195
Ian Rogers15bf2d32012-08-28 17:33:04 -07001196 // Try to avoid blocking GC during a send, but only safe when not using mutexes at a lower-level
1197 // than mutator for lock ordering reasons.
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001198 Thread* self = Thread::Current();
Ian Rogers62d6c772013-02-27 08:32:07 -08001199 bool safe_to_release_mutator_lock_over_send = !Locks::mutator_lock_->IsExclusiveHeld(self);
1200 if (safe_to_release_mutator_lock_over_send) {
Brian Carlstrom38f85e42013-07-18 14:45:22 -07001201 for (size_t i = 0; i < kMutatorLock; ++i) {
Ian Rogers62d6c772013-02-27 08:32:07 -08001202 if (self->GetHeldMutex(static_cast<LockLevel>(i)) != NULL) {
1203 safe_to_release_mutator_lock_over_send = false;
1204 break;
1205 }
Ian Rogers15bf2d32012-08-28 17:33:04 -07001206 }
1207 }
1208 if (safe_to_release_mutator_lock_over_send) {
1209 // Change state to waiting to allow GC, ... while we're sending.
1210 self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
Brian Carlstromf5293522013-07-19 00:24:00 -07001211 SendBufferedRequest(type, wrapiov);
Ian Rogers15bf2d32012-08-28 17:33:04 -07001212 self->TransitionFromSuspendedToRunnable();
1213 } else {
1214 // Send and possibly block GC...
Brian Carlstromf5293522013-07-19 00:24:00 -07001215 SendBufferedRequest(type, wrapiov);
Ian Rogers15bf2d32012-08-28 17:33:04 -07001216 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001217}
1218
1219} // namespace JDWP
1220
1221} // namespace art