jdwp_event.cc revision 4d25df3f76f864b7629ac8c0046d46997f293d8d
1872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
2872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
4872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * you may not use this file except in compliance with the License.
6872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * You may obtain a copy of the License at
7872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
8872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
10872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Unless required by applicable law or agreed to in writing, software
11872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See the License for the specific language governing permissions and
14872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * limitations under the License.
15872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1607ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes
17872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include "jdwp/jdwp_event.h"
18872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include <stddef.h>     /* for offsetof() */
20872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <stdlib.h>
21872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <string.h>
22872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#include <unistd.h>
23872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
2407ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
25e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h"
2607ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "debugger.h"
2707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_constants.h"
2807ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_expand_buf.h"
2907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "jdwp/jdwp_priv.h"
30693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "thread-inl.h"
3107ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes
32872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
33872d4ec7225444d9400d30f9027247deb91012fdElliott HughesGeneral notes:
34872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
35872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe event add/remove stuff usually happens from the debugger thread,
36872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesin response to requests from the debugger, but can also happen as the
37872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesresult of an event in an arbitrary thread (e.g. an event with a "count"
38872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmod expires).  It's important to keep the event list locked when processing
39872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesevents.
40872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
41872d4ec7225444d9400d30f9027247deb91012fdElliott HughesEvent posting can happen from any thread.  The JDWP thread will not usually
42872d4ec7225444d9400d30f9027247deb91012fdElliott Hughespost anything but VM start/death, but if a JDWP request causes a class
43872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesto be loaded, the ClassPrepare event will come from the JDWP thread.
44872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
45872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
46872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe can have serialization issues when we post an event to the debugger.
47872d4ec7225444d9400d30f9027247deb91012fdElliott HughesFor example, a thread could send an "I hit a breakpoint and am suspending
48872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesmyself" message to the debugger.  Before it manages to suspend itself, the
49872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdebugger's response ("not interested, resume thread") arrives and is
50872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesprocessed.  We try to resume a thread that hasn't yet suspended.
51872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
52872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThis means that, after posting an event to the debugger, we need to wait
53872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfor the event thread to suspend itself (and, potentially, all other threads)
54872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore processing any additional requests from the debugger.  While doing
55872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesso we need to be aware that multiple threads may be hitting breakpoints
56872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor other events simultaneously, so we either need to wait for all of them
57872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesor serialize the events with each other.
58872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
59872d4ec7225444d9400d30f9027247deb91012fdElliott HughesThe current mechanism works like this:
60872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  Event thread:
61872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If I'm going to suspend, grab the "I am posting an event" token.  Wait
62872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     for it if it's not currently available.
63872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - Post the event to the debugger.
64872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - If appropriate, suspend others and then myself.  As part of suspending
65872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     myself, release the "I am posting" token.
66872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JDWP thread:
67872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   - When an event arrives, see if somebody is posting an event.  If so,
68872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     sleep until we can acquire the "I am posting an event" token.  Release
69872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     it immediately and continue processing -- the event we have already
70872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     received should not interfere with other events that haven't yet
71872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     been posted.
72872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
73872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSome care must be taken to avoid deadlock:
74872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
75872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A and thread B exit near-simultaneously, and post thread-death
76872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   events with a "suspend all" clause
77872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A gets the event token, thread B sits and waits for it
78872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes - thread A wants to suspend all other threads, but thread B is waiting
79872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   for the token and can't be suspended
80872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
81872d4ec7225444d9400d30f9027247deb91012fdElliott HughesSo we need to mark thread B in such a way that thread A doesn't wait for it.
82872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
83872d4ec7225444d9400d30f9027247deb91012fdElliott HughesIf we just bracket the "grab event token" call with a change to VMWAIT
84872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesbefore sleeping, the switch back to RUNNING state when we get the token
85872d4ec7225444d9400d30f9027247deb91012fdElliott Hugheswill cause thread B to suspend (remember, thread A's global suspend is
86872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstill in force, even after it releases the token).  Suspending while
87872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesholding the event token is very bad, because it prevents the JDWP thread
88872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesfrom processing incoming messages.
89872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
90872d4ec7225444d9400d30f9027247deb91012fdElliott HughesWe need to change to VMWAIT state at the *start* of posting an event,
91872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesand stay there until we either finish posting the event or decide to
92872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesput ourselves to sleep.  That way we don't interfere with anyone else and
93872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesdon't allow anyone else to interfere with us.
94872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes*/
95872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
96872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
97872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpEventCommandSet    64
98872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes#define kJdwpCompositeCommand   100
99872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace art {
101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesnamespace JDWP {
103872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
104872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
105872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Stuff to compare against when deciding if a mod matches.  Only the
106872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * values for mods valid for the event being evaluated will be filled in.
107872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The rest will be zeroed.
108872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
109872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstruct ModBasket {
110162fd33474038f0de0388338ca007ecf400bb3dfjeffhao  ModBasket() : pLoc(NULL), threadId(0), classId(0), excepClassId(0),
111162fd33474038f0de0388338ca007ecf400bb3dfjeffhao                caught(false), field(0), thisPtr(0) { }
112162fd33474038f0de0388338ca007ecf400bb3dfjeffhao
113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  const JdwpLocation* pLoc;           /* LocationOnly */
114a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  std::string         className;      /* ClassMatch/ClassExclude */
115872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            threadId;       /* ThreadOnly */
116872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           classId;        /* ClassOnly */
117872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  RefTypeId           excepClassId;   /* ExceptionOnly */
118872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool                caught;         /* ExceptionOnly */
119872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  FieldId             field;          /* FieldOnly */
120872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId            thisPtr;        /* InstanceOnly */
121872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* nothing for StepOnly -- handled differently */
122872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes};
123872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
124872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
125872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Dump an event to the log file.
126872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
127872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic void dumpEvent(const JdwpEvent* pEvent) {
128872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  LOG(INFO) << StringPrintf("Event id=0x%4x %p (prev=%p next=%p):", pEvent->requestId, pEvent, pEvent->prev, pEvent->next);
129f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  LOG(INFO) << "  kind=" << pEvent->eventKind << " susp=" << pEvent->suspend_policy << " modCount=" << pEvent->modCount;
130872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
131872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
132872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpEventMod* pMod = &pEvent->mods[i];
1337b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes    LOG(INFO) << "  " << pMod->modKind;
134872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* TODO - show details */
135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
138138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertzstatic bool NeedsFullDeoptimization(JdwpEventKind eventKind) {
139138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  switch (eventKind) {
140138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      case EK_METHOD_ENTRY:
141138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      case EK_METHOD_EXIT:
142138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      case EK_METHOD_EXIT_WITH_RETURN_VALUE:
143138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      case EK_SINGLE_STEP:
144138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz        return true;
145138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      default:
146138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz        return false;
147138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    }
148138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz}
149138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
150872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
151872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Add an event to the list.  Ordering is not important.
152872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
153872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If something prevents the event from being registered, e.g. it's a
154872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * single-step request on a thread that doesn't exist, the event will
155872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * not be added to the list, and an appropriate error will be returned.
156872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
157761928d24e4e7ed7776b52243eaf9095ad35f448Elliott HughesJdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
158872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent != NULL);
159872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->prev == NULL);
160872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->next == NULL);
161872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
162872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
163872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If one or more "break"-type mods are used, register them with
164872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * the interpreter.
165872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1664d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  DeoptimizationRequest req;
167872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
168872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    const JdwpEventMod* pMod = &pEvent->mods[i];
169872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_LOCATION_ONLY) {
170872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for Breakpoint, Step, and Exception */
1714d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      Dbg::WatchLocation(&pMod->locationOnly.loc, &req);
172872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    } else if (pMod->modKind == MK_STEP) {
173872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for EK_SINGLE_STEP; should only be one */
174872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
175872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
1762435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      JdwpError status = Dbg::ConfigureStep(pMod->step.threadId, size, depth);
1772435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      if (status != ERR_NONE) {
1782435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes        return status;
1792435a5751431152aaeaa2faaa86b2a30d3eecfe3Elliott Hughes      }
180872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    } else if (pMod->modKind == MK_FIELD_ONLY) {
181872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should be for EK_FIELD_ACCESS or EK_FIELD_MODIFICATION */
182872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      dumpEvent(pEvent);  /* TODO - need for field watches */
183872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
184872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1854d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  if (NeedsFullDeoptimization(pEvent->eventKind)) {
1864d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
1874d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    CHECK(req.method == nullptr);
1884d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    req.kind = DeoptimizationRequest::kFullDeoptimization;
1894d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  }
190872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
191138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  {
192138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    /*
193138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz     * Add to list.
194138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz     */
195138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    MutexLock mu(Thread::Current(), event_list_lock_);
196138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    if (event_list_ != NULL) {
197138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      pEvent->next = event_list_;
198138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      event_list_->prev = pEvent;
199138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    }
200138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    event_list_ = pEvent;
201138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    ++event_list_size_;
202872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
203138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
2044d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  // TODO we can do better job here since we should process only one request: the one we just
2054d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  // created.
2064d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  Dbg::RequestDeoptimization(req);
207138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  Dbg::ManageDeoptimization();
208872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
209872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return ERR_NONE;
210872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
211872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
212872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
213872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove an event from the list.  This will also remove the event from
214872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any optimization tables, e.g. breakpoints.
215872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
216872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Does not free the JdwpEvent.
217872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
218872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Grab the eventLock before calling here.
219872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
220761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
221872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->prev == NULL) {
222872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* head of the list */
223f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CHECK(event_list_ == pEvent);
224872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
225f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    event_list_ = pEvent->next;
226872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
227872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->prev->next = pEvent->next;
228872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
229872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
230872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent->next != NULL) {
231872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next->prev = pEvent->prev;
232872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent->next = NULL;
233872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
234872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  pEvent->prev = NULL;
235872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
236872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
237872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Unhook us from the interpreter, if necessary.
238872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
2394d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  DeoptimizationRequest req;
240872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
241872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEventMod* pMod = &pEvent->mods[i];
242872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_LOCATION_ONLY) {
243872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for Breakpoint, Step, and Exception */
2444d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      Dbg::UnwatchLocation(&pMod->locationOnly.loc, &req);
245872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
246872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pMod->modKind == MK_STEP) {
247872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      /* should only be for EK_SINGLE_STEP; should only be one */
248872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      Dbg::UnconfigureStep(pMod->step.threadId);
249872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
250872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
2514d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  if (NeedsFullDeoptimization(pEvent->eventKind)) {
2524d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    CHECK_EQ(req.kind, DeoptimizationRequest::kNothing);
2534d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    CHECK(req.method == nullptr);
2544d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz    req.kind = DeoptimizationRequest::kFullUndeoptimization;
2554d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  }
256872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
257f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  --event_list_size_;
258f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  CHECK(event_list_size_ != 0 || event_list_ == NULL);
259138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
2604d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz  Dbg::RequestDeoptimization(req);
261872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
262872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
263872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
264872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove the event with the given ID from the list.
265872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
266872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Failure to find the event isn't really an error, but it is a little
267872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * weird.  (It looks like Eclipse will try to be extra careful and will
268872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * explicitly remove one-off single-step events.)
269872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
270761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterEventById(uint32_t requestId) {
271138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  bool found = false;
272138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  {
273138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    MutexLock mu(Thread::Current(), event_list_lock_);
274872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
275138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    for (JdwpEvent* pEvent = event_list_; pEvent != nullptr; pEvent = pEvent->next) {
276138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      if (pEvent->requestId == requestId) {
277138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz        found = true;
278138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz        UnregisterEvent(pEvent);
279138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz        EventFree(pEvent);
280138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz        break;      /* there can be only one with a given ID */
281138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      }
282872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
283872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
284872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
285138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  if (found) {
286138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    Dbg::ManageDeoptimization();
287138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  } else {
288138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    LOG(DEBUG) << StringPrintf("Odd: no match when removing event reqId=0x%04x", requestId);
289138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  }
290872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
291872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
292872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
293872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Remove all entries from the event list.
294872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
295761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::UnregisterAll() {
29650b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  MutexLock mu(Thread::Current(), event_list_lock_);
297872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
298f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
299872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
300872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pNextEvent = pEvent->next;
301872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
302761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    UnregisterEvent(pEvent);
303872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    EventFree(pEvent);
304872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pNextEvent;
305872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
306872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
307f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  event_list_ = NULL;
308872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
309872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
310872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
311872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate a JdwpEvent struct with enough space to hold the specified
312872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * number of mod records.
313872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
314872d4ec7225444d9400d30f9027247deb91012fdElliott HughesJdwpEvent* EventAlloc(int numMods) {
315872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEvent* newEvent;
316872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
317872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
318872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  memset(newEvent, 0, allocSize);
319872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return newEvent;
320872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
321872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
322872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
323872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Free a JdwpEvent.
324872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
325872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Do not call this until the event has been removed from the list.
326872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
327872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesvoid EventFree(JdwpEvent* pEvent) {
328872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pEvent == NULL) {
329872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
330872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
331872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
332872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* make sure it was removed from the list */
333872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->prev == NULL);
334872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(pEvent->next == NULL);
335f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  /* want to check state->event_list_ != pEvent */
336872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
337872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
338872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Free any hairy bits in the mods.
339872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
340872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = 0; i < pEvent->modCount; i++) {
341872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
342872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classMatch.classPattern);
343872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classMatch.classPattern = NULL;
344872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
345872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
346872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      free(pEvent->mods[i].classExclude.classPattern);
347872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pEvent->mods[i].classExclude.classPattern = NULL;
348872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
349872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
350872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
351872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  free(pEvent);
352872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
353872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
354872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
355872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Allocate storage for matching events.  To keep things simple we
356872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * use an array with enough storage for the entire list.
357872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
358872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The state->eventLock should be held before calling.
359872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
360761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic JdwpEvent** AllocMatchList(size_t event_count) {
361761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  return new JdwpEvent*[event_count];
362872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
363872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
364872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
365872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Run through the list and remove any entries with an expired "count" mod
366872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * from the event list, then free the match list.
367872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
368f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesvoid JdwpState::CleanupMatchList(JdwpEvent** match_list, int match_count) {
369f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent** ppEvent = match_list;
370872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
3712aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  while (match_count--) {
372872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    JdwpEvent* pEvent = *ppEvent;
373872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
374872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    for (int i = 0; i < pEvent->modCount; i++) {
375872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
3764dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "##### Removing expired event";
377761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        UnregisterEvent(pEvent);
378872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        EventFree(pEvent);
379872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        break;
380872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
381872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
382872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
383872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    ppEvent++;
384872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
385872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
386f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  delete[] match_list;
387872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
388872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
389872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
390872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Match a string against a "restricted regular expression", which is just
391872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
392872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
393872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * ("Restricted name globbing" might have been a better term.)
394872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
395761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesstatic bool PatternMatch(const char* pattern, const std::string& target) {
396a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes  size_t patLen = strlen(pattern);
397872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (pattern[0] == '*') {
398872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    patLen--;
399a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    if (target.size() < patLen) {
400872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      return false;
401872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
402a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strcmp(pattern+1, target.c_str() + (target.size()-patLen)) == 0;
403872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else if (pattern[patLen-1] == '*') {
404a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strncmp(pattern, target.c_str(), patLen-1) == 0;
405872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
406a215526d5c789cbef0f81a1f9aba22541a841ccaElliott Hughes    return strcmp(pattern, target.c_str()) == 0;
407872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
408872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
409872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
410872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
411872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * See if the event's mods match up with the contents of "basket".
412872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
413872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * If we find a Count mod before rejecting an event, we decrement it.  We
414872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * need to do this even if later mods cause us to ignore the event.
415872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
41600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic bool ModsMatch(JdwpEvent* pEvent, ModBasket* basket)
417b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
418872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpEventMod* pMod = pEvent->mods;
419872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
420872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  for (int i = pEvent->modCount; i > 0; i--, pMod++) {
421872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    switch (pMod->modKind) {
422872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_COUNT:
423872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK_GT(pMod->count.count, 0);
424872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      pMod->count.count--;
425872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
426872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CONDITIONAL:
427872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      CHECK(false);  // should not be getting these
428872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
429872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_THREAD_ONLY:
430872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->threadOnly.threadId != basket->threadId) {
431872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
432872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
433872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
434872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_ONLY:
435872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->classOnly.refTypeId)) {
436872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
437872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
438872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
439872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_MATCH:
440761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (!PatternMatch(pMod->classMatch.classPattern, basket->className)) {
441872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
442872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
443872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
444872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_CLASS_EXCLUDE:
445761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      if (PatternMatch(pMod->classMatch.classPattern, basket->className)) {
446872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
447872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
448872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
449872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_LOCATION_ONLY:
4502aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      if (pMod->locationOnly.loc != *basket->pLoc) {
451872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
452872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
453872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
454872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_EXCEPTION_ONLY:
455872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->exceptionOnly.refTypeId != 0 && !Dbg::MatchType(basket->excepClassId, pMod->exceptionOnly.refTypeId)) {
456872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
457872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
458872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if ((basket->caught && !pMod->exceptionOnly.caught) || (!basket->caught && !pMod->exceptionOnly.uncaught)) {
459872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
460872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
461872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
462872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_FIELD_ONLY:
463872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (!Dbg::MatchType(basket->classId, pMod->fieldOnly.refTypeId) || pMod->fieldOnly.fieldId != basket->field) {
464872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
465872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
466872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
467872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_STEP:
468872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->step.threadId != basket->threadId) {
469872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
470872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
471872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
472872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    case MK_INSTANCE_ONLY:
473872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      if (pMod->instanceOnly.objectId != basket->thisPtr) {
474872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes        return false;
475872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
476872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
477872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    default:
4787b3cdfcca472b779cf8745fb8460935e56229f11Elliott Hughes      LOG(FATAL) << "unknown mod kind " << pMod->modKind;
479872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
480872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
481872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
482872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
483872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
484872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
485872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
486872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Find all events of type "eventKind" with mods that match up with the
487872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * rest of the arguments.
488872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
489f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes * Found events are appended to "match_list", and "*pMatchCount" is advanced,
490872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * so this may be called multiple times for grouped events.
491872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
492872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * DO NOT call this multiple times for the same eventKind, as Count mods are
493872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * decremented during the scan.
494872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
49500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::FindMatchingEvents(JdwpEventKind eventKind, ModBasket* basket,
49600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                   JdwpEvent** match_list, int* pMatchCount) {
497872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* start after the existing entries */
498f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  match_list += *pMatchCount;
499872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
500f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpEvent* pEvent = event_list_;
501872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (pEvent != NULL) {
502761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if (pEvent->eventKind == eventKind && ModsMatch(pEvent, basket)) {
503f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      *match_list++ = pEvent;
504872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      (*pMatchCount)++;
505872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
506872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
507872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pEvent = pEvent->next;
508872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
509872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
510872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
511872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
512872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Scan through the list of matches and determine the most severe
513872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * suspension policy.
514872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
515f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughesstatic JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** match_list, int match_count) {
516872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  JdwpSuspendPolicy policy = SP_NONE;
517872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
5182aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  while (match_count--) {
519f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    if ((*match_list)->suspend_policy > policy) {
520f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      policy = (*match_list)->suspend_policy;
521872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
522f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    match_list++;
523872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
524872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
525872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return policy;
526872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
527872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
528872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
529872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Three possibilities:
530872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_NONE - do nothing
531872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_EVENT_THREAD - suspend ourselves
532872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  SP_ALL - suspend everybody except JDWP support thread
533872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
53400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspend_policy, JDWP::ObjectId thread_self_id) {
535f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  VLOG(jdwp) << "SuspendByPolicy(" << suspend_policy << ")";
536f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (suspend_policy == SP_NONE) {
537872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
538872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
539872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
540f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  if (suspend_policy == SP_ALL) {
541475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    Dbg::SuspendVM();
542872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
543f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CHECK_EQ(suspend_policy, SP_EVENT_THREAD);
544872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
545872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
546872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is rare but possible -- see CLASS_PREPARE handling */
54700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (thread_self_id == debug_thread_id_) {
548761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    LOG(INFO) << "NOTE: SuspendByPolicy not suspending JDWP thread";
549872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return;
550872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
551872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
552872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
553872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  while (true) {
554872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = true;
555872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::SuspendSelf();
556872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    pReq->ready = false;
557872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
558872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /*
559872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * The JDWP thread has told us (and possibly all other threads) to
560872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     * resume.  See if it has left anything in our DebugInvokeReq mailbox.
561872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes     */
562d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz    if (!pReq->invoke_needed) {
563761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      /*LOGD("SuspendByPolicy: no invoke needed");*/
564872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      break;
565872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
566872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
567872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    /* grab this before posting/suspending again */
56800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SetWaitForEventThread(thread_self_id);
569872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
570d07986fad0d08cdf05505cf9230714a2cf0dd9aeElliott Hughes    /* leave pReq->invoke_needed_ raised so we can check reentrancy */
571872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    Dbg::ExecuteMethod(pReq);
572872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
573475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes    pReq->error = ERR_NONE;
574872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
575872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
576872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
57700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersvoid JdwpState::SendRequestAndPossiblySuspend(ExpandBuf* pReq, JdwpSuspendPolicy suspend_policy,
57800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                              ObjectId threadId) {
57900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
58000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  self->AssertThreadSuspensionIsAllowable();
58100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  /* send request and possibly suspend ourselves */
58200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (pReq != NULL) {
58300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    JDWP::ObjectId thread_self_id = Dbg::GetThreadSelfId();
58400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
58500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    if (suspend_policy != SP_NONE) {
58600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      SetWaitForEventThread(threadId);
58700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
58800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    EventFinish(pReq);
58900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    SuspendByPolicy(suspend_policy, thread_self_id);
59000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    self->TransitionFromSuspendedToRunnable();
59100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
59200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}
59300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers
594872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
595872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Determine if there is a method invocation in progress in the current
596872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * thread.
597872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
598475fc23a4a7f35d1be87ea0b06c80df317a720acElliott Hughes * We look at the "invoke_needed" flag in the per-thread DebugInvokeReq
599872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * state.  If set, we're in the process of invoking a method.
600872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
601761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::InvokeInProgress() {
602872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
603d38667a055d507492fd05f78519a7e1f0b85ea03Sebastien Hertz  return pReq->invoke_needed;
604872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
605872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
606872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
607872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * We need the JDWP thread to hold off on doing stuff while we post an
608872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * event and then suspend ourselves.
609872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
610872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Call this with a threadId of zero if you just want to wait for the
611872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * current thread operation to complete.
612872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
613872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This could go to sleep waiting for another thread, so it's important
614872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * that the thread be marked as VMWAIT before calling here.
615872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
616376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::SetWaitForEventThread(ObjectId threadId) {
617872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  bool waited = false;
618872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
619872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* this is held for very brief periods; contention is unlikely */
62081d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  Thread* self = Thread::Current();
62181d425b0b232962441616f8b14f73620bffef5e5Ian Rogers  MutexLock mu(self, event_thread_lock_);
622872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
623872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
624872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If another thread is already doing stuff, wait for it.  This can
625872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * go to sleep indefinitely.
626872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
627a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  while (event_thread_id_ != 0) {
628d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers    VLOG(jdwp) << StringPrintf("event in progress (%#" PRIx64 "), %#" PRIx64 " sleeping",
629d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                               event_thread_id_, threadId);
630872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    waited = true;
631c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers    event_thread_cond_.Wait(self);
632872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
633872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
634872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (waited || threadId != 0) {
635d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers    VLOG(jdwp) << StringPrintf("event token grabbed (%#" PRIx64 ")", threadId);
636872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
637872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  if (threadId != 0) {
638a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes    event_thread_id_ = threadId;
639872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
640872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
641872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
642872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
643872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Clear the threadId and signal anybody waiting.
644872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
645376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesvoid JdwpState::ClearWaitForEventThread() {
646872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
647872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
648872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * function is called by dvmSuspendSelf(), and the transition back
649872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * to RUNNING would confuse it.
650872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
651c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  Thread* self = Thread::Current();
652c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  MutexLock mu(self, event_thread_lock_);
653872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
654a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  CHECK_NE(event_thread_id_, 0U);
655d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers  VLOG(jdwp) << StringPrintf("cleared event token (%#" PRIx64 ")", event_thread_id_);
656872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
657a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  event_thread_id_ = 0;
658872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
659c604d731730b43231f63040c8db1d58304da0cf3Ian Rogers  event_thread_cond_.Signal(self);
660872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
661872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
662872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
663872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
664872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Prep an event.  Allocates storage for the message and leaves space for
665872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the header.
666872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
667872d4ec7225444d9400d30f9027247deb91012fdElliott Hughesstatic ExpandBuf* eventPrep() {
668872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = expandBufAlloc();
669872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAddSpace(pReq, kJDWPHeaderLen);
670872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return pReq;
671872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
672872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
673872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
674872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Write the header into the buffer and send the packet off to the debugger.
675872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
676872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Takes ownership of "pReq" (currently discards it).
677872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
678761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesvoid JdwpState::EventFinish(ExpandBuf* pReq) {
679872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t* buf = expandBufGetBuffer(pReq);
680872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
681f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(buf, expandBufGetLength(pReq));
682761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  Set4BE(buf+4, NextRequestSerial());
683f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+8, 0);     /* flags */
684f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+9, kJdwpEventCommandSet);
685f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(buf+10, kJdwpCompositeCommand);
686872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
68799660e1c3d6117cfb8bac25b1a0413833ab15b2aSebastien Hertz  // Prevents from interleaving commands and events. Otherwise we could end up in sending an event
68899660e1c3d6117cfb8bac25b1a0413833ab15b2aSebastien Hertz  // before sending the reply of the command being processed and would lead to bad synchronization
68999660e1c3d6117cfb8bac25b1a0413833ab15b2aSebastien Hertz  // between the debugger and the debuggee.
69099660e1c3d6117cfb8bac25b1a0413833ab15b2aSebastien Hertz  WaitForProcessingRequest();
69199660e1c3d6117cfb8bac25b1a0413833ab15b2aSebastien Hertz
692761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  SendRequest(pReq);
693872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
694872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufFree(pReq);
695872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
696872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
697872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
698872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
699872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Tell the debugger that we have finished initializing.  This is always
700872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * sent, even if the debugger hasn't requested it.
701872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
702872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * This should be sent "before the main thread is started and before
703872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * any application code has been executed".  The thread ID in the message
704872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * must be for the main thread.
705872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
706376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::PostVMStart() {
707f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy;
708872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ObjectId threadId = Dbg::GetThreadSelfId();
709872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
710376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughes  if (options_->suspend) {
711f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    suspend_policy = SP_ALL;
712872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  } else {
713f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    suspend_policy = SP_NONE;
714872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
715872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
716761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  ExpandBuf* pReq = eventPrep();
717761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
7187934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    MutexLock mu(Thread::Current(), event_list_lock_);  // probably don't need this here
719872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
7204dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "EVENT: " << EK_VM_START;
721f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
722872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
723f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    expandBufAdd1(pReq, suspend_policy);
724872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 1);
725872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
726872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd1(pReq, EK_VM_START);
727872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd4BE(pReq, 0);       /* requestId */
728872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    expandBufAdd8BE(pReq, threadId);
729872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
730872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
731138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  Dbg::ManageDeoptimization();
732138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
733872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* send request and possibly suspend ourselves */
73400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, threadId);
735872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
736872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
737872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
738872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
739872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
740872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A location of interest has been reached.  This handles:
741872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Breakpoint
742872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   SingleStep
743872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodEntry
744872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   MethodExit
745872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * These four types must be grouped together in a single response.  The
746872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * "eventFlags" indicates the type of event(s) that have happened.
747872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
748872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
749872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
750872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   LocationOnly (for breakpoint/step only)
751872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *   Step (for step only)
752872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
753872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Interesting test cases:
754872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Put a breakpoint on a native method.  Eclipse creates METHOD_ENTRY
755872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    and METHOD_EXIT events with a ClassOnly mod on the method's class.
756872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Use "run to line".  Eclipse creates a BREAKPOINT with Count=1.
757872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  - Single-step to a line with a breakpoint.  Should get a single
758872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    event message with both events in it.
759872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
760579b02416e05e32e535126e1ed61613a2cdb030eJeff Haobool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags,
761579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao                                  const JValue* returnValue) {
762872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
763872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pLoc;
764748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.classId = pLoc->class_id;
765872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
766872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
767748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.className = Dbg::GetClassName(pLoc->class_id);
768872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
769872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
770872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * On rare occasions we may need to execute interpreted code in the VM
771872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while handling a request from the debugger.  Don't fire breakpoints
772872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * while doing so.  (I don't think we currently do this at all, so
773872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this is mostly paranoia.)
774872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
775a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  if (basket.threadId == debug_thread_id_) {
7764dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Ignoring location event in JDWP thread";
777872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
778872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
779872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
780872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
781872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * The debugger variable display tab may invoke the interpreter to format
782872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * complex objects.  We want to ignore breakpoints and method entry/exit
783872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * traps while working on behalf of the debugger.
784872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   *
785872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * If we don't ignore them, the VM will get hung up, because we'll
786872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * suspend on a breakpoint while the debugger is still waiting for its
787872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * method invocation to complete.
788872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
789761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
7904dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not checking breakpoints during invoke (" << basket.className << ")";
791872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
792872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
793872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
7942aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
795872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
796f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
797761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
79850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
799138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    JdwpEvent** match_list = AllocMatchList(event_list_size_);
8008696433d1b3d8ba15288483b777edd888de69135Elliott Hughes    if ((eventFlags & Dbg::kBreakpoint) != 0) {
801f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_BREAKPOINT, &basket, match_list, &match_count);
802761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
803761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kSingleStep) != 0) {
804f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_SINGLE_STEP, &basket, match_list, &match_count);
805761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
806761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodEntry) != 0) {
807f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_METHOD_ENTRY, &basket, match_list, &match_count);
808761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
809761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    if ((eventFlags & Dbg::kMethodExit) != 0) {
810f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_METHOD_EXIT, &basket, match_list, &match_count);
811579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao      FindMatchingEvents(EK_METHOD_EXIT_WITH_RETURN_VALUE, &basket, match_list, &match_count);
812761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes    }
8132aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
814f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
815a96836a4115ad08762567c10bd4d198c5b644985Elliott Hughes                 << basket.className << "." << Dbg::GetMethodName(pLoc->method_id)
816d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                 << StringPrintf(" thread=%#" PRIx64 "  dex_pc=%#" PRIx64 ")",
817d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                                 basket.threadId, pLoc->dex_pc);
818872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
819f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
820f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
821872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
822761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
823f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
8242aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
825761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
8262aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
827f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
828f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
829761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
8306e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pLoc);
831579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao        if (match_list[i]->eventKind == EK_METHOD_EXIT_WITH_RETURN_VALUE) {
832579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao          Dbg::OutputMethodReturnValue(pLoc->method_id, returnValue, pReq);
833579b02416e05e32e535126e1ed61613a2cdb030eJeff Hao        }
834761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
835872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
836872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
837f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
838761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  }
839872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
840138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  Dbg::ManageDeoptimization();
841138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
84200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
8432aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
844872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
845872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
846872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
847872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * A thread is starting or stopping.
848872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
849872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
850872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly
851872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
852234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughesbool JdwpState::PostThreadChange(ObjectId threadId, bool start) {
853872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK_EQ(threadId, Dbg::GetThreadSelfId());
854872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
855872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
856872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * I don't think this can happen.
857872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
858761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
859872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    LOG(WARNING) << "Not posting thread change during invoke";
860872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
861872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
862872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
863872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
864872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = threadId;
865872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
866872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
867f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
8682aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
869234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  {
870234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    // Don't allow the list to be updated while we scan it.
87150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
872f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    JdwpEvent** match_list = AllocMatchList(event_list_size_);
873234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
874234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    if (start) {
875f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_THREAD_START, &basket, match_list, &match_count);
876234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    } else {
877f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      FindMatchingEvents(EK_THREAD_DEATH, &basket, match_list, &match_count);
878234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes    }
879872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
8802aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
881f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
882d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                 << StringPrintf("thread=%#" PRIx64, basket.threadId) << ")";
883872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
884f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
885f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
886872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
887234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      pReq = eventPrep();
888f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
8892aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
890234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes
8912aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
892f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
893f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
894234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
895234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes      }
896872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
897872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
898f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
899234ab15b00f8120282d1833e5d7480eca2e35a29Elliott Hughes  }
900872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
901138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  Dbg::ManageDeoptimization();
902138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
90300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
904872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9052aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
906872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
907872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
908872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
909872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send a polite "VM is dying" message to the debugger.
910872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
911872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Skips the usual "event token" stuff.
912872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
913376a7a033d29d5f2b6e16574a340c999ff2999a0Elliott Hughesbool JdwpState::PostVMDeath() {
9144dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes  VLOG(jdwp) << "EVENT: " << EK_VM_DEATH;
915872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
916872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = eventPrep();
917872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd1(pReq, SP_NONE);
918872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReq, 1);
919872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
920872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd1(pReq, EK_VM_DEATH);
921872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  expandBufAdd4BE(pReq, 0);
922761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  EventFinish(pReq);
923872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  return true;
924872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
925872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
926872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
927872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * An exception has been thrown.  It may or may not have been caught.
928872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
929872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
930872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
931872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *    ExceptionOnly, InstanceOnly
932872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
933872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * The "exceptionId" has not been added to the GC-visible object registry,
934872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * because there's a pretty good chance that we're not going to send it
935872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * up the debugger.
936872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
937761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughesbool JdwpState::PostException(const JdwpLocation* pThrowLoc,
938748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes                              ObjectId exceptionId, RefTypeId exceptionClassId,
939748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes                              const JdwpLocation* pCatchLoc, ObjectId thisPtr) {
940872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
941872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
942872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.pLoc = pThrowLoc;
943748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.classId = pThrowLoc->class_id;
944872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
945c308a5d8c1993ff51be355531548e91409bdbd82Elliott Hughes  basket.className = Dbg::GetClassName(basket.classId);
946872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.excepClassId = exceptionClassId;
947748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  basket.caught = (pCatchLoc->class_id != 0);
948872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.thisPtr = thisPtr;
949872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
950872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* don't try to post an exception caused by the debugger */
951761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
9524dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not posting exception hit during invoke (" << basket.className << ")";
953872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
954872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
955872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9562aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  int match_count = 0;
957872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
958f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
959761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
96050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
961138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz    JdwpEvent** match_list = AllocMatchList(event_list_size_);
962f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    FindMatchingEvents(EK_EXCEPTION, &basket, match_list, &match_count);
9632aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
964f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total)"
965d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                 << StringPrintf(" thread=%#" PRIx64, basket.threadId)
966d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                 << StringPrintf(" exceptId=%#" PRIx64, exceptionId)
967436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes                 << " caught=" << basket.caught << ")"
968436e372e1c2b8e0bde47408e7407b4c3590f5071Elliott Hughes                 << "  throw: " << *pThrowLoc;
969748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes      if (pCatchLoc->class_id == 0) {
9704dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  catch: (not caught)";
971761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      } else {
9724dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  catch: " << *pCatchLoc;
973761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
974872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
975f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
976f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
977872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
978761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
979f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
9802aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
981761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes
9822aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
983f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
984f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
985761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
986872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
9876e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pThrowLoc);
988761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, JT_OBJECT);
989761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, exceptionId);
9906e9d22c78c1016e70f8c2a9e6bc66c94ec36f728Elliott Hughes        expandBufAddLocation(pReq, *pCatchLoc);
991761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
992872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
993872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
994f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
995872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
996872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
997138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  Dbg::ManageDeoptimization();
998138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
99900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
1000872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10012aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
1002872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1003872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1004872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1005872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Announce that a class has been loaded.
1006872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1007872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Valid mods:
1008872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
1009872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
101000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersbool JdwpState::PostClassPrepare(JdwpTypeTag tag, RefTypeId refTypeId, const std::string& signature,
101100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                                 int status) {
1012872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ModBasket basket;
1013872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1014872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.classId = refTypeId;
1015872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  basket.threadId = Dbg::GetThreadSelfId();
1016c308a5d8c1993ff51be355531548e91409bdbd82Elliott Hughes  basket.className = Dbg::GetClassName(basket.classId);
1017872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1018872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* suppress class prep caused by debugger */
1019761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  if (InvokeInProgress()) {
10204dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes    VLOG(jdwp) << "Not posting class prep caused by invoke (" << basket.className << ")";
1021872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    return false;
1022872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1023872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1024872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  ExpandBuf* pReq = NULL;
1025f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  JdwpSuspendPolicy suspend_policy = SP_NONE;
1026f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes  int match_count = 0;
1027761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes  {
102850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    MutexLock mu(Thread::Current(), event_list_lock_);
1029f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    JdwpEvent** match_list = AllocMatchList(event_list_size_);
1030f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    FindMatchingEvents(EK_CLASS_PREPARE, &basket, match_list, &match_count);
10312aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes    if (match_count != 0) {
1032f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "EVENT: " << match_list[0]->eventKind << "(" << match_count << " total) "
1033d9e4e0c8606f8b87e0a48aab68125dbee543bf88Ian Rogers                 << StringPrintf("thread=%#" PRIx64, basket.threadId) << ") " << signature;
1034872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1035f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      suspend_policy = scanSuspendPolicy(match_list, match_count);
1036f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
1037872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1038a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes      if (basket.threadId == debug_thread_id_) {
1039761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        /*
1040761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * JDWP says that, for a class prep in the debugger thread, we
1041761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * should set threadId to null and if any threads were supposed
1042761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         * to be suspended then we suspend all other threads.
1043761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes         */
10444dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes        VLOG(jdwp) << "  NOTE: class prepare in debugger thread!";
1045761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        basket.threadId = 0;
1046f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        if (suspend_policy == SP_EVENT_THREAD) {
1047f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes          suspend_policy = SP_ALL;
1048761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        }
1049872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes      }
1050872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1051761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      pReq = eventPrep();
1052f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes      expandBufAdd1(pReq, suspend_policy);
10532aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      expandBufAdd4BE(pReq, match_count);
1054872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10552aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes      for (int i = 0; i < match_count; i++) {
1056f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd1(pReq, match_list[i]->eventKind);
1057f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes        expandBufAdd4BE(pReq, match_list[i]->requestId);
1058761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, basket.threadId);
1059872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1060761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd1(pReq, tag);
1061761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd8BE(pReq, refTypeId);
1062761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAddUtf8String(pReq, signature);
1063761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes        expandBufAdd4BE(pReq, status);
1064761928d24e4e7ed7776b52243eaf9095ad35f448Elliott Hughes      }
1065872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    }
1066f8349361a16a4e2796efe9f3586b994e8d4834e4Elliott Hughes    CleanupMatchList(match_list, match_count);
1067872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1068872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1069138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  Dbg::ManageDeoptimization();
1070138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
107100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  SendRequestAndPossiblySuspend(pReq, suspend_policy, basket.threadId);
1072872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
10732aa2e39548e194c5514d6534149ca1078021eab1Elliott Hughes  return match_count != 0;
1074872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1075872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1076872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes/*
1077872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * Send up a chunk of DDM data.
1078872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes *
1079872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * While this takes the form of a JDWP "event", it doesn't interact with
1080872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * other debugger traffic, and can't suspend the VM, so we skip all of
1081872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes * the fun event token gymnastics.
1082872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes */
1083cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughesvoid JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
1084872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  uint8_t header[kJDWPHeaderLen + 8];
1085872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  size_t dataLen = 0;
1086872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1087872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  CHECK(iov != NULL);
1088cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  CHECK_GT(iov_count, 0);
1089cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  CHECK_LT(iov_count, 10);
1090872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1091872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /*
1092872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * "Wrap" the contents of the iovec with a JDWP/DDMS header.  We do
1093872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   * this by creating a new copy of the vector with space for the header.
1094872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes   */
1095f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom  std::vector<iovec> wrapiov;
1096f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom  wrapiov.push_back(iovec());
1097cccd84f1f972f1a260c3be418c8388a5d30cf59eElliott Hughes  for (int i = 0; i < iov_count; i++) {
1098f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom    wrapiov.push_back(iov[i]);
1099872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes    dataLen += iov[i].iov_len;
1100872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  }
1101872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1102872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  /* form the header (JDWP plus DDMS) */
1103f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header, sizeof(header) + dataLen);
1104f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+4, NextRequestSerial());
1105f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+8, 0);     /* flags */
1106f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+9, kJDWPDdmCmdSet);
1107f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set1(header+10, kJDWPDdmCmd);
1108f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+11, type);
1109f7c3b6625d710a8700325eea447f65e9f963b7f2Elliott Hughes  Set4BE(header+15, dataLen);
1110872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1111872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_base = header;
1112872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes  wrapiov[0].iov_len = sizeof(header);
1113872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
111415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  // Try to avoid blocking GC during a send, but only safe when not using mutexes at a lower-level
111515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  // than mutator for lock ordering reasons.
111600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread* self = Thread::Current();
111762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool safe_to_release_mutator_lock_over_send = !Locks::mutator_lock_->IsExclusiveHeld(self);
111862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (safe_to_release_mutator_lock_over_send) {
111938f85e4892f6504971bde994fec81fd61780ac30Brian Carlstrom    for (size_t i = 0; i < kMutatorLock; ++i) {
112062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      if (self->GetHeldMutex(static_cast<LockLevel>(i)) != NULL) {
112162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        safe_to_release_mutator_lock_over_send = false;
112262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers        break;
112362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      }
112415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    }
112515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  }
112615bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  if (safe_to_release_mutator_lock_over_send) {
112715bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // Change state to waiting to allow GC, ... while we're sending.
112815bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
1129f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom    SendBufferedRequest(type, wrapiov);
113015bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    self->TransitionFromSuspendedToRunnable();
113115bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  } else {
113215bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    // Send and possibly block GC...
1133f52935278fca8c7aa220543eef4544e3d1105d91Brian Carlstrom    SendBufferedRequest(type, wrapiov);
113415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers  }
1135872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}
1136872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1137872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace JDWP
1138872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes
1139872d4ec7225444d9400d30f9027247deb91012fdElliott Hughes}  // namespace art
1140