/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "jdwp/jdwp_event.h"

#include <stddef.h>     /* for offsetof() */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/logging.h"
#include "base/stringprintf.h"
#include "debugger.h"
#include "jdwp/jdwp_constants.h"
#include "jdwp/jdwp_expand_buf.h"
#include "jdwp/jdwp_priv.h"
#include "jdwp/object_registry.h"
#include "scoped_thread_state_change.h"
#include "thread-inl.h"

#include "handle_scope-inl.h"

/*
General notes:

The event add/remove stuff usually happens from the debugger thread,
in response to requests from the debugger, but can also happen as the
result of an event in an arbitrary thread (e.g. an event with a "count"
mod expires).  It's important to keep the event list locked when processing
events.

Event posting can happen from any thread.  The JDWP thread will not usually
post anything but VM start/death, but if a JDWP request causes a class
to be loaded, the ClassPrepare event will come from the JDWP thread.


We can have serialization issues when we post an event to the debugger.
For example, a thread could send an "I hit a breakpoint and am suspending
myself" message to the debugger.  Before it manages to suspend itself, the
debugger's response ("not interested, resume thread") arrives and is
processed.  We try to resume a thread that hasn't yet suspended.

This means that, after posting an event to the debugger, we need to wait
for the event thread to suspend itself (and, potentially, all other threads)
before processing any additional requests from the debugger.  While doing
so we need to be aware that multiple threads may be hitting breakpoints
or other events simultaneously, so we either need to wait for all of them
or serialize the events with each other.

The current mechanism works like this:
  Event thread:
   - If I'm going to suspend, grab the "I am posting an event" token.  Wait
     for it if it's not currently available.
   - Post the event to the debugger.
   - If appropriate, suspend others and then myself.  As part of suspending
     myself, release the "I am posting" token.
  JDWP thread:
   - When an event arrives, see if somebody is posting an event.  If so,
     sleep until we can acquire the "I am posting an event" token.  Release
     it immediately and continue processing -- the event we have already
     received should not interfere with other events that haven't yet
     been posted.

Some care must be taken to avoid deadlock:

 - thread A and thread B exit near-simultaneously, and post thread-death
   events with a "suspend all" clause
 - thread A gets the event token, thread B sits and waits for it
 - thread A wants to suspend all other threads, but thread B is waiting
   for the token and can't be suspended

So we need to mark thread B in such a way that thread A doesn't wait for it.

If we just bracket the "grab event token" call with a change to VMWAIT
before sleeping, the switch back to RUNNING state when we get the token
will cause thread B to suspend (remember, thread A's global suspend is
still in force, even after it releases the token).  Suspending while
holding the event token is very bad, because it prevents the JDWP thread
from processing incoming messages.

We need to change to VMWAIT state at the *start* of posting an event,
and stay there until we either finish posting the event or decide to
put ourselves to sleep.  That way we don't interfere with anyone else and
don't allow anyone else to interfere with us.
*/


#define kJdwpEventCommandSet    64
#define kJdwpCompositeCommand   100

namespace art {

namespace JDWP {

/*
 * Stuff to compare against when deciding if a mod matches.  Only the
 * values for mods valid for the event being evaluated will be filled in.
 * The rest will be zeroed.
 * Must be allocated on the stack only. This is enforced by removing the
 * operator new.
 */
struct ModBasket {
  explicit ModBasket(Thread* self)
    : hs(self), pLoc(nullptr), thread(self),
      locationClass(hs.NewHandle<mirror::Class>(nullptr)),
      exceptionClass(hs.NewHandle<mirror::Class>(nullptr)),
      caught(false),
      field(nullptr),
      thisPtr(hs.NewHandle<mirror::Object>(nullptr)) { }

  StackHandleScope<3> hs;
  const EventLocation*            pLoc;             /* LocationOnly */
  std::string                     className;        /* ClassMatch/ClassExclude */
  Thread* const                   thread;           /* ThreadOnly */
  MutableHandle<mirror::Class>    locationClass;    /* ClassOnly */
  MutableHandle<mirror::Class>    exceptionClass;   /* ExceptionOnly */
  bool                            caught;           /* ExceptionOnly */
  ArtField*                       field;            /* FieldOnly */
  MutableHandle<mirror::Object>   thisPtr;          /* InstanceOnly */
  /* nothing for StepOnly -- handled differently */

 private:
  DISALLOW_ALLOCATION();  // forbids allocation on the heap.
  DISALLOW_IMPLICIT_CONSTRUCTORS(ModBasket);
};

static bool NeedsFullDeoptimization(JdwpEventKind eventKind) {
  if (!Dbg::RequiresDeoptimization()) {
    // We don't need deoptimization for debugging.
    return false;
  }
  switch (eventKind) {
      case EK_METHOD_ENTRY:
      case EK_METHOD_EXIT:
      case EK_METHOD_EXIT_WITH_RETURN_VALUE:
      case EK_FIELD_ACCESS:
      case EK_FIELD_MODIFICATION:
        return true;
      default:
        return false;
    }
}

// Returns the instrumentation event the DebugInstrumentationListener must
// listen to in order to properly report the given JDWP event to the debugger.
static uint32_t GetInstrumentationEventFor(JdwpEventKind eventKind) {
  switch (eventKind) {
    case EK_BREAKPOINT:
    case EK_SINGLE_STEP:
      return instrumentation::Instrumentation::kDexPcMoved;
    case EK_EXCEPTION:
    case EK_EXCEPTION_CATCH:
      return instrumentation::Instrumentation::kExceptionCaught;
    case EK_METHOD_ENTRY:
      return instrumentation::Instrumentation::kMethodEntered;
    case EK_METHOD_EXIT:
    case EK_METHOD_EXIT_WITH_RETURN_VALUE:
      return instrumentation::Instrumentation::kMethodExited;
    case EK_FIELD_ACCESS:
      return instrumentation::Instrumentation::kFieldRead;
    case EK_FIELD_MODIFICATION:
      return instrumentation::Instrumentation::kFieldWritten;
    default:
      return 0;
  }
}

/*
 * Add an event to the list.  Ordering is not important.
 *
 * If something prevents the event from being registered, e.g. it's a
 * single-step request on a thread that doesn't exist, the event will
 * not be added to the list, and an appropriate error will be returned.
 */
JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) {
  CHECK(pEvent != nullptr);
  CHECK(pEvent->prev == nullptr);
  CHECK(pEvent->next == nullptr);

  {
    /*
     * If one or more "break"-type mods are used, register them with
     * the interpreter.
     */
    DeoptimizationRequest req;
    for (int i = 0; i < pEvent->modCount; i++) {
      const JdwpEventMod* pMod = &pEvent->mods[i];
      if (pMod->modKind == MK_LOCATION_ONLY) {
        // Should only concern breakpoint, field access, field modification, step, and exception
        // events.
        // However breakpoint requires specific handling. Field access, field modification and step
        // events need full deoptimization to be reported while exception event is reported during
        // exception handling.
        if (pEvent->eventKind == EK_BREAKPOINT) {
          Dbg::WatchLocation(&pMod->locationOnly.loc, &req);
        }
      } else if (pMod->modKind == MK_STEP) {
        /* should only be for EK_SINGLE_STEP; should only be one */
        JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
        JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
        JdwpError status = Dbg::ConfigureStep(pMod->step.threadId, size, depth);
        if (status != ERR_NONE) {
          return status;
        }
      }
    }
    if (NeedsFullDeoptimization(pEvent->eventKind)) {
      CHECK_EQ(req.GetKind(), DeoptimizationRequest::kNothing);
      CHECK(req.Method() == nullptr);
      req.SetKind(DeoptimizationRequest::kFullDeoptimization);
    }
    Dbg::RequestDeoptimization(req);
  }
  uint32_t instrumentation_event = GetInstrumentationEventFor(pEvent->eventKind);
  if (instrumentation_event != 0) {
    DeoptimizationRequest req;
    req.SetKind(DeoptimizationRequest::kRegisterForEvent);
    req.SetInstrumentationEvent(instrumentation_event);
    Dbg::RequestDeoptimization(req);
  }

  {
    /*
     * Add to list.
     */
    MutexLock mu(Thread::Current(), event_list_lock_);
    if (event_list_ != nullptr) {
      pEvent->next = event_list_;
      event_list_->prev = pEvent;
    }
    event_list_ = pEvent;
    ++event_list_size_;
  }

  Dbg::ManageDeoptimization();

  return ERR_NONE;
}

/*
 * Remove an event from the list.  This will also remove the event from
 * any optimization tables, e.g. breakpoints.
 *
 * Does not free the JdwpEvent.
 *
 * Grab the eventLock before calling here.
 */
void JdwpState::UnregisterEvent(JdwpEvent* pEvent) {
  if (pEvent->prev == nullptr) {
    /* head of the list */
    CHECK(event_list_ == pEvent);

    event_list_ = pEvent->next;
  } else {
    pEvent->prev->next = pEvent->next;
  }

  if (pEvent->next != nullptr) {
    pEvent->next->prev = pEvent->prev;
    pEvent->next = nullptr;
  }
  pEvent->prev = nullptr;

  {
    /*
     * Unhook us from the interpreter, if necessary.
     */
    DeoptimizationRequest req;
    for (int i = 0; i < pEvent->modCount; i++) {
      JdwpEventMod* pMod = &pEvent->mods[i];
      if (pMod->modKind == MK_LOCATION_ONLY) {
        // Like in RegisterEvent, we need specific handling for breakpoint only.
        if (pEvent->eventKind == EK_BREAKPOINT) {
          Dbg::UnwatchLocation(&pMod->locationOnly.loc, &req);
        }
      }
      if (pMod->modKind == MK_STEP) {
        /* should only be for EK_SINGLE_STEP; should only be one */
        Dbg::UnconfigureStep(pMod->step.threadId);
      }
    }
    if (NeedsFullDeoptimization(pEvent->eventKind)) {
      CHECK_EQ(req.GetKind(), DeoptimizationRequest::kNothing);
      CHECK(req.Method() == nullptr);
      req.SetKind(DeoptimizationRequest::kFullUndeoptimization);
    }
    Dbg::RequestDeoptimization(req);
  }
  uint32_t instrumentation_event = GetInstrumentationEventFor(pEvent->eventKind);
  if (instrumentation_event != 0) {
    DeoptimizationRequest req;
    req.SetKind(DeoptimizationRequest::kUnregisterForEvent);
    req.SetInstrumentationEvent(instrumentation_event);
    Dbg::RequestDeoptimization(req);
  }

  --event_list_size_;
  CHECK(event_list_size_ != 0 || event_list_ == nullptr);
}

/*
 * Remove the event with the given ID from the list.
 *
 */
void JdwpState::UnregisterEventById(uint32_t requestId) {
  bool found = false;
  {
    MutexLock mu(Thread::Current(), event_list_lock_);

    for (JdwpEvent* pEvent = event_list_; pEvent != nullptr; pEvent = pEvent->next) {
      if (pEvent->requestId == requestId) {
        found = true;
        UnregisterEvent(pEvent);
        EventFree(pEvent);
        break;      /* there can be only one with a given ID */
      }
    }
  }

  if (found) {
    Dbg::ManageDeoptimization();
  } else {
    // Failure to find the event isn't really an error. For instance, it looks like Eclipse will
    // try to be extra careful and will explicitly remove one-off single-step events (using a
    // 'count' event modifier of 1). So the event may have already been removed as part of the
    // event notification (see JdwpState::CleanupMatchList).
    VLOG(jdwp) << StringPrintf("No match when removing event reqId=0x%04x", requestId);
  }
}

/*
 * Remove all entries from the event list.
 */
void JdwpState::UnregisterAll() {
  MutexLock mu(Thread::Current(), event_list_lock_);

  JdwpEvent* pEvent = event_list_;
  while (pEvent != nullptr) {
    JdwpEvent* pNextEvent = pEvent->next;

    UnregisterEvent(pEvent);
    EventFree(pEvent);
    pEvent = pNextEvent;
  }

  event_list_ = nullptr;
}

/*
 * Allocate a JdwpEvent struct with enough space to hold the specified
 * number of mod records.
 */
JdwpEvent* EventAlloc(int numMods) {
  JdwpEvent* newEvent;
  int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
  newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
  memset(newEvent, 0, allocSize);
  return newEvent;
}

/*
 * Free a JdwpEvent.
 *
 * Do not call this until the event has been removed from the list.
 */
void EventFree(JdwpEvent* pEvent) {
  if (pEvent == nullptr) {
    return;
  }

  /* make sure it was removed from the list */
  CHECK(pEvent->prev == nullptr);
  CHECK(pEvent->next == nullptr);
  /* want to check state->event_list_ != pEvent */

  /*
   * Free any hairy bits in the mods.
   */
  for (int i = 0; i < pEvent->modCount; i++) {
    if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
      free(pEvent->mods[i].classMatch.classPattern);
      pEvent->mods[i].classMatch.classPattern = nullptr;
    }
    if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
      free(pEvent->mods[i].classExclude.classPattern);
      pEvent->mods[i].classExclude.classPattern = nullptr;
    }
  }

  free(pEvent);
}

/*
 * Run through the list and remove any entries with an expired "count" mod
 * from the event list.
 */
void JdwpState::CleanupMatchList(const std::vector<JdwpEvent*>& match_list) {
  for (JdwpEvent* pEvent : match_list) {
    for (int i = 0; i < pEvent->modCount; ++i) {
      if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
        VLOG(jdwp) << StringPrintf("##### Removing expired event (requestId=%#" PRIx32 ")",
                                   pEvent->requestId);
        UnregisterEvent(pEvent);
        EventFree(pEvent);
        break;
      }
    }
  }
}

/*
 * Match a string against a "restricted regular expression", which is just
 * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
 *
 * ("Restricted name globbing" might have been a better term.)
 */
static bool PatternMatch(const char* pattern, const std::string& target) {
  size_t patLen = strlen(pattern);
  if (pattern[0] == '*') {
    patLen--;
    if (target.size() < patLen) {
      return false;
    }
    return strcmp(pattern+1, target.c_str() + (target.size()-patLen)) == 0;
  } else if (pattern[patLen-1] == '*') {
    return strncmp(pattern, target.c_str(), patLen-1) == 0;
  } else {
    return strcmp(pattern, target.c_str()) == 0;
  }
}

/*
 * See if the event's mods match up with the contents of "basket".
 *
 * If we find a Count mod before rejecting an event, we decrement it.  We
 * need to do this even if later mods cause us to ignore the event.
 */
static bool ModsMatch(JdwpEvent* pEvent, const ModBasket& basket)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  JdwpEventMod* pMod = pEvent->mods;

  for (int i = pEvent->modCount; i > 0; i--, pMod++) {
    switch (pMod->modKind) {
    case MK_COUNT:
      CHECK_GT(pMod->count.count, 0);
      pMod->count.count--;
      if (pMod->count.count > 0) {
        return false;
      }
      break;
    case MK_CONDITIONAL:
      CHECK(false);  // should not be getting these
      break;
    case MK_THREAD_ONLY:
      if (!Dbg::MatchThread(pMod->threadOnly.threadId, basket.thread)) {
        return false;
      }
      break;
    case MK_CLASS_ONLY:
      if (!Dbg::MatchType(basket.locationClass.Get(), pMod->classOnly.refTypeId)) {
        return false;
      }
      break;
    case MK_CLASS_MATCH:
      if (!PatternMatch(pMod->classMatch.classPattern, basket.className)) {
        return false;
      }
      break;
    case MK_CLASS_EXCLUDE:
      if (PatternMatch(pMod->classMatch.classPattern, basket.className)) {
        return false;
      }
      break;
    case MK_LOCATION_ONLY:
      if (!Dbg::MatchLocation(pMod->locationOnly.loc, *basket.pLoc)) {
        return false;
      }
      break;
    case MK_EXCEPTION_ONLY:
      if (pMod->exceptionOnly.refTypeId != 0 &&
          !Dbg::MatchType(basket.exceptionClass.Get(), pMod->exceptionOnly.refTypeId)) {
        return false;
      }
      if ((basket.caught && !pMod->exceptionOnly.caught) ||
          (!basket.caught && !pMod->exceptionOnly.uncaught)) {
        return false;
      }
      break;
    case MK_FIELD_ONLY:
      if (!Dbg::MatchField(pMod->fieldOnly.refTypeId, pMod->fieldOnly.fieldId, basket.field)) {
        return false;
      }
      break;
    case MK_STEP:
      if (!Dbg::MatchThread(pMod->step.threadId, basket.thread)) {
        return false;
      }
      break;
    case MK_INSTANCE_ONLY:
      if (!Dbg::MatchInstance(pMod->instanceOnly.objectId, basket.thisPtr.Get())) {
        return false;
      }
      break;
    default:
      LOG(FATAL) << "unknown mod kind " << pMod->modKind;
      break;
    }
  }
  return true;
}

/*
 * Find all events of type "event_kind" with mods that match up with the
 * rest of the arguments while holding the event list lock. This method
 * is used by FindMatchingEvents below.
 *
 * Found events are appended to "match_list" so this may be called multiple times for grouped
 * events.
 *
 * DO NOT call this multiple times for the same eventKind, as Count mods are
 * decremented during the scan.
 */
void JdwpState::FindMatchingEventsLocked(JdwpEventKind event_kind, const ModBasket& basket,
                                         std::vector<JdwpEvent*>* match_list) {
  for (JdwpEvent* pEvent = event_list_; pEvent != nullptr; pEvent = pEvent->next) {
    if (pEvent->eventKind == event_kind && ModsMatch(pEvent, basket)) {
      match_list->push_back(pEvent);
    }
  }
}

/*
 * Find all events of type "event_kind" with mods that match up with the
 * rest of the arguments and return true if at least one event matches,
 * false otherwise.
 *
 * Found events are appended to "match_list" so this may be called multiple
 * times for grouped events.
 *
 * DO NOT call this multiple times for the same eventKind, as Count mods are
 * decremented during the scan.
 */
bool JdwpState::FindMatchingEvents(JdwpEventKind event_kind, const ModBasket& basket,
                                   std::vector<JdwpEvent*>* match_list) {
  MutexLock mu(Thread::Current(), event_list_lock_);
  match_list->reserve(event_list_size_);
  FindMatchingEventsLocked(event_kind, basket, match_list);
  return !match_list->empty();
}

/*
 * Scan through the list of matches and determine the most severe
 * suspension policy.
 */
static JdwpSuspendPolicy ScanSuspendPolicy(const std::vector<JdwpEvent*>& match_list) {
  JdwpSuspendPolicy policy = SP_NONE;

  for (JdwpEvent* pEvent : match_list) {
    if (pEvent->suspend_policy > policy) {
      policy = pEvent->suspend_policy;
    }
  }

  return policy;
}

/*
 * Three possibilities:
 *  SP_NONE - do nothing
 *  SP_EVENT_THREAD - suspend ourselves
 *  SP_ALL - suspend everybody except JDWP support thread
 */
void JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspend_policy, JDWP::ObjectId thread_self_id) {
  VLOG(jdwp) << "SuspendByPolicy(" << suspend_policy << ")";
  if (suspend_policy == SP_NONE) {
    return;
  }

  if (suspend_policy == SP_ALL) {
    Dbg::SuspendVM();
  } else {
    CHECK_EQ(suspend_policy, SP_EVENT_THREAD);
  }

  /* this is rare but possible -- see CLASS_PREPARE handling */
  if (thread_self_id == debug_thread_id_) {
    LOG(INFO) << "NOTE: SuspendByPolicy not suspending JDWP thread";
    return;
  }

  while (true) {
    Dbg::SuspendSelf();

    /*
     * The JDWP thread has told us (and possibly all other threads) to
     * resume.  See if it has left anything in our DebugInvokeReq mailbox.
     */
    DebugInvokeReq* const pReq = Dbg::GetInvokeReq();
    if (pReq == nullptr) {
      /*LOGD("SuspendByPolicy: no invoke needed");*/
      break;
    }

    /* grab this before posting/suspending again */
    AcquireJdwpTokenForEvent(thread_self_id);

    Dbg::ExecuteMethod(pReq);
  }
}

void JdwpState::SendRequestAndPossiblySuspend(ExpandBuf* pReq, JdwpSuspendPolicy suspend_policy,
                                              ObjectId threadId) {
  Thread* const self = Thread::Current();
  self->AssertThreadSuspensionIsAllowable();
  CHECK(pReq != nullptr);
  /* send request and possibly suspend ourselves */
  JDWP::ObjectId thread_self_id = Dbg::GetThreadSelfId();
  self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
  if (suspend_policy != SP_NONE) {
    AcquireJdwpTokenForEvent(threadId);
  }
  EventFinish(pReq);
  {
    // Before suspending, we change our state to kSuspended so the debugger sees us as RUNNING.
    ScopedThreadStateChange stsc(self, kSuspended);
    SuspendByPolicy(suspend_policy, thread_self_id);
  }
  self->TransitionFromSuspendedToRunnable();
}

/*
 * Determine if there is a method invocation in progress in the current
 * thread.
 *
 * We look at the "invoke_needed" flag in the per-thread DebugInvokeReq
 * state.  If set, we're in the process of invoking a method.
 */
bool JdwpState::InvokeInProgress() {
  DebugInvokeReq* pReq = Dbg::GetInvokeReq();
  return pReq != nullptr;
}

void JdwpState::AcquireJdwpTokenForCommand() {
  CHECK_EQ(Thread::Current(), GetDebugThread()) << "Expected debugger thread";
  SetWaitForJdwpToken(debug_thread_id_);
}

void JdwpState::ReleaseJdwpTokenForCommand() {
  CHECK_EQ(Thread::Current(), GetDebugThread()) << "Expected debugger thread";
  ClearWaitForJdwpToken();
}

void JdwpState::AcquireJdwpTokenForEvent(ObjectId threadId) {
  CHECK_NE(Thread::Current(), GetDebugThread()) << "Expected event thread";
  CHECK_NE(debug_thread_id_, threadId) << "Not expected debug thread";
  SetWaitForJdwpToken(threadId);
}

void JdwpState::ReleaseJdwpTokenForEvent() {
  CHECK_NE(Thread::Current(), GetDebugThread()) << "Expected event thread";
  ClearWaitForJdwpToken();
}

/*
 * We need the JDWP thread to hold off on doing stuff while we post an
 * event and then suspend ourselves.
 *
 * This could go to sleep waiting for another thread, so it's important
 * that the thread be marked as VMWAIT before calling here.
 */
void JdwpState::SetWaitForJdwpToken(ObjectId threadId) {
  bool waited = false;
  Thread* const self = Thread::Current();
  CHECK_NE(threadId, 0u);
  CHECK_NE(self->GetState(), kRunnable);
  Locks::mutator_lock_->AssertNotHeld(self);

  /* this is held for very brief periods; contention is unlikely */
  MutexLock mu(self, jdwp_token_lock_);

  CHECK_NE(jdwp_token_owner_thread_id_, threadId) << "Thread is already holding event thread lock";

  /*
   * If another thread is already doing stuff, wait for it.  This can
   * go to sleep indefinitely.
   */
  while (jdwp_token_owner_thread_id_ != 0) {
    VLOG(jdwp) << StringPrintf("event in progress (%#" PRIx64 "), %#" PRIx64 " sleeping",
                               jdwp_token_owner_thread_id_, threadId);
    waited = true;
    jdwp_token_cond_.Wait(self);
  }

  if (waited || threadId != debug_thread_id_) {
    VLOG(jdwp) << StringPrintf("event token grabbed (%#" PRIx64 ")", threadId);
  }
  jdwp_token_owner_thread_id_ = threadId;
}

/*
 * Clear the threadId and signal anybody waiting.
 */
void JdwpState::ClearWaitForJdwpToken() {
  /*
   * Grab the mutex.  Don't try to go in/out of VMWAIT mode, as this
   * function is called by Dbg::SuspendSelf(), and the transition back
   * to RUNNING would confuse it.
   */
  Thread* const self = Thread::Current();
  MutexLock mu(self, jdwp_token_lock_);

  CHECK_NE(jdwp_token_owner_thread_id_, 0U);
  VLOG(jdwp) << StringPrintf("cleared event token (%#" PRIx64 ")", jdwp_token_owner_thread_id_);

  jdwp_token_owner_thread_id_ = 0;
  jdwp_token_cond_.Signal(self);
}

/*
 * Prep an event.  Allocates storage for the message and leaves space for
 * the header.
 */
static ExpandBuf* eventPrep() {
  ExpandBuf* pReq = expandBufAlloc();
  expandBufAddSpace(pReq, kJDWPHeaderLen);
  return pReq;
}

/*
 * Write the header into the buffer and send the packet off to the debugger.
 *
 * Takes ownership of "pReq" (currently discards it).
 */
void JdwpState::EventFinish(ExpandBuf* pReq) {
  uint8_t* buf = expandBufGetBuffer(pReq);

  Set4BE(buf, expandBufGetLength(pReq));
  Set4BE(buf + 4, NextRequestSerial());
  Set1(buf + 8, 0);     /* flags */
  Set1(buf + 9, kJdwpEventCommandSet);
  Set1(buf + 10, kJdwpCompositeCommand);

  SendRequest(pReq);

  expandBufFree(pReq);
}


/*
 * Tell the debugger that we have finished initializing.  This is always
 * sent, even if the debugger hasn't requested it.
 *
 * This should be sent "before the main thread is started and before
 * any application code has been executed".  The thread ID in the message
 * must be for the main thread.
 */
void JdwpState::PostVMStart() {
  JdwpSuspendPolicy suspend_policy = (options_->suspend) ? SP_ALL : SP_NONE;
  ObjectId threadId = Dbg::GetThreadSelfId();

  VLOG(jdwp) << "EVENT: " << EK_VM_START;
  VLOG(jdwp) << "  suspend_policy=" << suspend_policy;

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, suspend_policy);
  expandBufAdd4BE(pReq, 1);
  expandBufAdd1(pReq, EK_VM_START);
  expandBufAdd4BE(pReq, 0);       /* requestId */
  expandBufAddObjectId(pReq, threadId);

  Dbg::ManageDeoptimization();

  /* send request and possibly suspend ourselves */
  SendRequestAndPossiblySuspend(pReq, suspend_policy, threadId);
}

static void LogMatchingEventsAndThread(const std::vector<JdwpEvent*> match_list,
                                       ObjectId thread_id)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  for (size_t i = 0, e = match_list.size(); i < e; ++i) {
    JdwpEvent* pEvent = match_list[i];
    VLOG(jdwp) << "EVENT #" << i << ": " << pEvent->eventKind
               << StringPrintf(" (requestId=%#" PRIx32 ")", pEvent->requestId);
  }
  std::string thread_name;
  JdwpError error = Dbg::GetThreadName(thread_id, &thread_name);
  if (error != JDWP::ERR_NONE) {
    thread_name = "<unknown>";
  }
  VLOG(jdwp) << StringPrintf("  thread=%#" PRIx64, thread_id) << " " << thread_name;
}

static void SetJdwpLocationFromEventLocation(const JDWP::EventLocation* event_location,
                                             JDWP::JdwpLocation* jdwp_location)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(event_location != nullptr);
  DCHECK(jdwp_location != nullptr);
  Dbg::SetJdwpLocation(jdwp_location, event_location->method, event_location->dex_pc);
}

/*
 * A location of interest has been reached.  This handles:
 *   Breakpoint
 *   SingleStep
 *   MethodEntry
 *   MethodExit
 * These four types must be grouped together in a single response.  The
 * "eventFlags" indicates the type of event(s) that have happened.
 *
 * Valid mods:
 *   Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
 *   LocationOnly (for breakpoint/step only)
 *   Step (for step only)
 *
 * Interesting test cases:
 *  - Put a breakpoint on a native method.  Eclipse creates METHOD_ENTRY
 *    and METHOD_EXIT events with a ClassOnly mod on the method's class.
 *  - Use "run to line".  Eclipse creates a BREAKPOINT with Count=1.
 *  - Single-step to a line with a breakpoint.  Should get a single
 *    event message with both events in it.
 */
void JdwpState::PostLocationEvent(const EventLocation* pLoc, mirror::Object* thisPtr,
                                  int eventFlags, const JValue* returnValue) {
  DCHECK(pLoc != nullptr);
  DCHECK(pLoc->method != nullptr);
  DCHECK_EQ(pLoc->method->IsStatic(), thisPtr == nullptr);

  ModBasket basket(Thread::Current());
  basket.pLoc = pLoc;
  basket.locationClass.Assign(pLoc->method->GetDeclaringClass());
  basket.thisPtr.Assign(thisPtr);
  basket.className = Dbg::GetClassName(basket.locationClass.Get());

  /*
   * On rare occasions we may need to execute interpreted code in the VM
   * while handling a request from the debugger.  Don't fire breakpoints
   * while doing so.  (I don't think we currently do this at all, so
   * this is mostly paranoia.)
   */
  if (basket.thread == GetDebugThread()) {
    VLOG(jdwp) << "Ignoring location event in JDWP thread";
    return;
  }

  /*
   * The debugger variable display tab may invoke the interpreter to format
   * complex objects.  We want to ignore breakpoints and method entry/exit
   * traps while working on behalf of the debugger.
   *
   * If we don't ignore them, the VM will get hung up, because we'll
   * suspend on a breakpoint while the debugger is still waiting for its
   * method invocation to complete.
   */
  if (InvokeInProgress()) {
    VLOG(jdwp) << "Not checking breakpoints during invoke (" << basket.className << ")";
    return;
  }

  std::vector<JdwpEvent*> match_list;
  {
    // We use the locked version because we have multiple possible match events.
    MutexLock mu(Thread::Current(), event_list_lock_);
    match_list.reserve(event_list_size_);
    if ((eventFlags & Dbg::kBreakpoint) != 0) {
      FindMatchingEventsLocked(EK_BREAKPOINT, basket, &match_list);
    }
    if ((eventFlags & Dbg::kSingleStep) != 0) {
      FindMatchingEventsLocked(EK_SINGLE_STEP, basket, &match_list);
    }
    if ((eventFlags & Dbg::kMethodEntry) != 0) {
      FindMatchingEventsLocked(EK_METHOD_ENTRY, basket, &match_list);
    }
    if ((eventFlags & Dbg::kMethodExit) != 0) {
      FindMatchingEventsLocked(EK_METHOD_EXIT, basket, &match_list);
      FindMatchingEventsLocked(EK_METHOD_EXIT_WITH_RETURN_VALUE, basket, &match_list);
    }
  }
  if (match_list.empty()) {
    // No matching event.
    return;
  }
  JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);

  ObjectId thread_id = Dbg::GetThreadId(basket.thread);
  JDWP::JdwpLocation jdwp_location;
  SetJdwpLocationFromEventLocation(pLoc, &jdwp_location);

  if (VLOG_IS_ON(jdwp)) {
    LogMatchingEventsAndThread(match_list, thread_id);
    VLOG(jdwp) << "  location=" << jdwp_location;
    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
  }

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, suspend_policy);
  expandBufAdd4BE(pReq, match_list.size());

  for (const JdwpEvent* pEvent : match_list) {
    expandBufAdd1(pReq, pEvent->eventKind);
    expandBufAdd4BE(pReq, pEvent->requestId);
    expandBufAddObjectId(pReq, thread_id);
    expandBufAddLocation(pReq, jdwp_location);
    if (pEvent->eventKind == EK_METHOD_EXIT_WITH_RETURN_VALUE) {
      Dbg::OutputMethodReturnValue(jdwp_location.method_id, returnValue, pReq);
    }
  }

  {
    MutexLock mu(Thread::Current(), event_list_lock_);
    CleanupMatchList(match_list);
  }

  Dbg::ManageDeoptimization();

  SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
}

void JdwpState::PostFieldEvent(const EventLocation* pLoc, ArtField* field,
                               mirror::Object* this_object, const JValue* fieldValue,
                               bool is_modification) {
  DCHECK(pLoc != nullptr);
  DCHECK(field != nullptr);
  DCHECK_EQ(fieldValue != nullptr, is_modification);
  DCHECK_EQ(field->IsStatic(), this_object == nullptr);

  ModBasket basket(Thread::Current());
  basket.pLoc = pLoc;
  basket.locationClass.Assign(pLoc->method->GetDeclaringClass());
  basket.thisPtr.Assign(this_object);
  basket.className = Dbg::GetClassName(basket.locationClass.Get());
  basket.field = field;

  if (InvokeInProgress()) {
    VLOG(jdwp) << "Not posting field event during invoke (" << basket.className << ")";
    return;
  }

  std::vector<JdwpEvent*> match_list;
  const JdwpEventKind match_kind = (is_modification) ? EK_FIELD_MODIFICATION : EK_FIELD_ACCESS;
  if (!FindMatchingEvents(match_kind, basket, &match_list)) {
    // No matching event.
    return;
  }

  JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
  ObjectId thread_id = Dbg::GetThreadId(basket.thread);
  ObjectRegistry* registry = Dbg::GetObjectRegistry();
  ObjectId instance_id = registry->Add(basket.thisPtr);
  RefTypeId field_type_id = registry->AddRefType(field->GetDeclaringClass());
  FieldId field_id = Dbg::ToFieldId(field);
  JDWP::JdwpLocation jdwp_location;
  SetJdwpLocationFromEventLocation(pLoc, &jdwp_location);

  if (VLOG_IS_ON(jdwp)) {
    LogMatchingEventsAndThread(match_list, thread_id);
    VLOG(jdwp) << "  location=" << jdwp_location;
    VLOG(jdwp) << StringPrintf("  this=%#" PRIx64, instance_id);
    VLOG(jdwp) << StringPrintf("  type=%#" PRIx64, field_type_id) << " "
        << Dbg::GetClassName(field_id);
    VLOG(jdwp) << StringPrintf("  field=%#" PRIx64, field_id) << " "
        << Dbg::GetFieldName(field_id);
    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
  }

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, suspend_policy);
  expandBufAdd4BE(pReq, match_list.size());

  // Get field's reference type tag.
  JDWP::JdwpTypeTag type_tag = Dbg::GetTypeTag(field->GetDeclaringClass());

  // Get instance type tag.
  uint8_t tag;
  {
    ScopedObjectAccessUnchecked soa(Thread::Current());
    tag = Dbg::TagFromObject(soa, basket.thisPtr.Get());
  }

  for (const JdwpEvent* pEvent : match_list) {
    expandBufAdd1(pReq, pEvent->eventKind);
    expandBufAdd4BE(pReq, pEvent->requestId);
    expandBufAddObjectId(pReq, thread_id);
    expandBufAddLocation(pReq, jdwp_location);
    expandBufAdd1(pReq, type_tag);
    expandBufAddRefTypeId(pReq, field_type_id);
    expandBufAddFieldId(pReq, field_id);
    expandBufAdd1(pReq, tag);
    expandBufAddObjectId(pReq, instance_id);
    if (is_modification) {
      Dbg::OutputFieldValue(field_id, fieldValue, pReq);
    }
  }

  {
    MutexLock mu(Thread::Current(), event_list_lock_);
    CleanupMatchList(match_list);
  }

  Dbg::ManageDeoptimization();

  SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
}

/*
 * A thread is starting or stopping.
 *
 * Valid mods:
 *  Count, ThreadOnly
 */
void JdwpState::PostThreadChange(Thread* thread, bool start) {
  CHECK_EQ(thread, Thread::Current());

  /*
   * I don't think this can happen.
   */
  if (InvokeInProgress()) {
    LOG(WARNING) << "Not posting thread change during invoke";
    return;
  }

  // We need the java.lang.Thread object associated to the starting/ending
  // thread to get its JDWP id. Therefore we can't report event if there
  // is no Java peer. This happens when the runtime shuts down and re-attaches
  // the current thread without creating a Java peer.
  if (thread->GetPeer() == nullptr) {
    return;
  }

  ModBasket basket(thread);

  std::vector<JdwpEvent*> match_list;
  const JdwpEventKind match_kind = (start) ? EK_THREAD_START : EK_THREAD_DEATH;
  if (!FindMatchingEvents(match_kind, basket, &match_list)) {
    // No matching event.
    return;
  }

  JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
  ObjectId thread_id = Dbg::GetThreadId(basket.thread);

  if (VLOG_IS_ON(jdwp)) {
    LogMatchingEventsAndThread(match_list, thread_id);
    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
  }

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, suspend_policy);
  expandBufAdd4BE(pReq, match_list.size());

  for (const JdwpEvent* pEvent : match_list) {
    expandBufAdd1(pReq, pEvent->eventKind);
    expandBufAdd4BE(pReq, pEvent->requestId);
    expandBufAdd8BE(pReq, thread_id);
  }

  {
    MutexLock mu(Thread::Current(), event_list_lock_);
    CleanupMatchList(match_list);
  }

  Dbg::ManageDeoptimization();

  SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
}

/*
 * Send a polite "VM is dying" message to the debugger.
 *
 * Skips the usual "event token" stuff.
 */
bool JdwpState::PostVMDeath() {
  VLOG(jdwp) << "EVENT: " << EK_VM_DEATH;

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, SP_NONE);
  expandBufAdd4BE(pReq, 1);

  expandBufAdd1(pReq, EK_VM_DEATH);
  expandBufAdd4BE(pReq, 0);
  EventFinish(pReq);
  return true;
}

/*
 * An exception has been thrown.  It may or may not have been caught.
 *
 * Valid mods:
 *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
 *    ExceptionOnly, InstanceOnly
 *
 * The "exceptionId" has not been added to the GC-visible object registry,
 * because there's a pretty good chance that we're not going to send it
 * up the debugger.
 */
void JdwpState::PostException(const EventLocation* pThrowLoc, mirror::Throwable* exception_object,
                              const EventLocation* pCatchLoc, mirror::Object* thisPtr) {
  DCHECK(exception_object != nullptr);
  DCHECK(pThrowLoc != nullptr);
  DCHECK(pCatchLoc != nullptr);
  if (pThrowLoc->method != nullptr) {
    DCHECK_EQ(pThrowLoc->method->IsStatic(), thisPtr == nullptr);
  } else {
    VLOG(jdwp) << "Unexpected: exception event with empty throw location";
  }

  ModBasket basket(Thread::Current());
  basket.pLoc = pThrowLoc;
  if (pThrowLoc->method != nullptr) {
    basket.locationClass.Assign(pThrowLoc->method->GetDeclaringClass());
  }
  basket.className = Dbg::GetClassName(basket.locationClass.Get());
  basket.exceptionClass.Assign(exception_object->GetClass());
  basket.caught = (pCatchLoc->method != 0);
  basket.thisPtr.Assign(thisPtr);

  /* don't try to post an exception caused by the debugger */
  if (InvokeInProgress()) {
    VLOG(jdwp) << "Not posting exception hit during invoke (" << basket.className << ")";
    return;
  }

  std::vector<JdwpEvent*> match_list;
  if (!FindMatchingEvents(EK_EXCEPTION, basket, &match_list)) {
    // No matching event.
    return;
  }

  JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
  ObjectId thread_id = Dbg::GetThreadId(basket.thread);
  ObjectRegistry* registry = Dbg::GetObjectRegistry();
  ObjectId exceptionId = registry->Add(exception_object);
  JDWP::JdwpLocation jdwp_throw_location;
  JDWP::JdwpLocation jdwp_catch_location;
  SetJdwpLocationFromEventLocation(pThrowLoc, &jdwp_throw_location);
  SetJdwpLocationFromEventLocation(pCatchLoc, &jdwp_catch_location);

  if (VLOG_IS_ON(jdwp)) {
    std::string exceptionClassName(PrettyDescriptor(exception_object->GetClass()));

    LogMatchingEventsAndThread(match_list, thread_id);
    VLOG(jdwp) << "  throwLocation=" << jdwp_throw_location;
    if (jdwp_catch_location.class_id == 0) {
      VLOG(jdwp) << "  catchLocation=uncaught";
    } else {
      VLOG(jdwp) << "  catchLocation=" << jdwp_catch_location;
    }
    VLOG(jdwp) << StringPrintf("  exception=%#" PRIx64, exceptionId) << " "
        << exceptionClassName;
    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
  }

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, suspend_policy);
  expandBufAdd4BE(pReq, match_list.size());

  for (const JdwpEvent* pEvent : match_list) {
    expandBufAdd1(pReq, pEvent->eventKind);
    expandBufAdd4BE(pReq, pEvent->requestId);
    expandBufAddObjectId(pReq, thread_id);
    expandBufAddLocation(pReq, jdwp_throw_location);
    expandBufAdd1(pReq, JT_OBJECT);
    expandBufAddObjectId(pReq, exceptionId);
    expandBufAddLocation(pReq, jdwp_catch_location);
  }

  {
    MutexLock mu(Thread::Current(), event_list_lock_);
    CleanupMatchList(match_list);
  }

  Dbg::ManageDeoptimization();

  SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
}

/*
 * Announce that a class has been loaded.
 *
 * Valid mods:
 *  Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
 */
void JdwpState::PostClassPrepare(mirror::Class* klass) {
  DCHECK(klass != nullptr);

  ModBasket basket(Thread::Current());
  basket.locationClass.Assign(klass);
  basket.className = Dbg::GetClassName(basket.locationClass.Get());

  /* suppress class prep caused by debugger */
  if (InvokeInProgress()) {
    VLOG(jdwp) << "Not posting class prep caused by invoke (" << basket.className << ")";
    return;
  }

  std::vector<JdwpEvent*> match_list;
  if (!FindMatchingEvents(EK_CLASS_PREPARE, basket, &match_list)) {
    // No matching event.
    return;
  }

  JdwpSuspendPolicy suspend_policy = ScanSuspendPolicy(match_list);
  ObjectId thread_id = Dbg::GetThreadId(basket.thread);
  ObjectRegistry* registry = Dbg::GetObjectRegistry();
  RefTypeId class_id = registry->AddRefType(basket.locationClass);

  // OLD-TODO - we currently always send both "verified" and "prepared" since
  // debuggers seem to like that.  There might be some advantage to honesty,
  // since the class may not yet be verified.
  int status = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
  JDWP::JdwpTypeTag tag = Dbg::GetTypeTag(basket.locationClass.Get());
  std::string temp;
  std::string signature(basket.locationClass->GetDescriptor(&temp));

  if (VLOG_IS_ON(jdwp)) {
    LogMatchingEventsAndThread(match_list, thread_id);
    VLOG(jdwp) << StringPrintf("  type=%#" PRIx64, class_id) << " " << signature;
    VLOG(jdwp) << "  suspend_policy=" << suspend_policy;
  }

  if (thread_id == debug_thread_id_) {
    /*
     * JDWP says that, for a class prep in the debugger thread, we
     * should set thread to null and if any threads were supposed
     * to be suspended then we suspend all other threads.
     */
    VLOG(jdwp) << "  NOTE: class prepare in debugger thread!";
    thread_id = 0;
    if (suspend_policy == SP_EVENT_THREAD) {
      suspend_policy = SP_ALL;
    }
  }

  ExpandBuf* pReq = eventPrep();
  expandBufAdd1(pReq, suspend_policy);
  expandBufAdd4BE(pReq, match_list.size());

  for (const JdwpEvent* pEvent : match_list) {
    expandBufAdd1(pReq, pEvent->eventKind);
    expandBufAdd4BE(pReq, pEvent->requestId);
    expandBufAddObjectId(pReq, thread_id);
    expandBufAdd1(pReq, tag);
    expandBufAddRefTypeId(pReq, class_id);
    expandBufAddUtf8String(pReq, signature);
    expandBufAdd4BE(pReq, status);
  }

  {
    MutexLock mu(Thread::Current(), event_list_lock_);
    CleanupMatchList(match_list);
  }

  Dbg::ManageDeoptimization();

  SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id);
}

/*
 * Setup the header for a chunk of DDM data.
 */
void JdwpState::SetupChunkHeader(uint32_t type, size_t data_len, size_t header_size,
                                 uint8_t* out_header) {
  CHECK_EQ(header_size, static_cast<size_t>(kJDWPHeaderLen + 8));
  /* form the header (JDWP plus DDMS) */
  Set4BE(out_header, header_size + data_len);
  Set4BE(out_header + 4, NextRequestSerial());
  Set1(out_header + 8, 0);     /* flags */
  Set1(out_header + 9, kJDWPDdmCmdSet);
  Set1(out_header + 10, kJDWPDdmCmd);
  Set4BE(out_header + 11, type);
  Set4BE(out_header + 15, data_len);
}

/*
 * Send up a chunk of DDM data.
 *
 * While this takes the form of a JDWP "event", it doesn't interact with
 * other debugger traffic, and can't suspend the VM, so we skip all of
 * the fun event token gymnastics.
 */
void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
  uint8_t header[kJDWPHeaderLen + 8] = { 0 };
  size_t dataLen = 0;

  CHECK(iov != nullptr);
  CHECK_GT(iov_count, 0);
  CHECK_LT(iov_count, 10);

  /*
   * "Wrap" the contents of the iovec with a JDWP/DDMS header.  We do
   * this by creating a new copy of the vector with space for the header.
   */
  std::vector<iovec> wrapiov;
  wrapiov.push_back(iovec());
  for (int i = 0; i < iov_count; i++) {
    wrapiov.push_back(iov[i]);
    dataLen += iov[i].iov_len;
  }

  SetupChunkHeader(type, dataLen, sizeof(header), header);

  wrapiov[0].iov_base = header;
  wrapiov[0].iov_len = sizeof(header);

  // Try to avoid blocking GC during a send, but only safe when not using mutexes at a lower-level
  // than mutator for lock ordering reasons.
  Thread* self = Thread::Current();
  bool safe_to_release_mutator_lock_over_send = !Locks::mutator_lock_->IsExclusiveHeld(self);
  if (safe_to_release_mutator_lock_over_send) {
    for (size_t i = 0; i < kMutatorLock; ++i) {
      if (self->GetHeldMutex(static_cast<LockLevel>(i)) != nullptr) {
        safe_to_release_mutator_lock_over_send = false;
        break;
      }
    }
  }
  if (safe_to_release_mutator_lock_over_send) {
    // Change state to waiting to allow GC, ... while we're sending.
    self->TransitionFromRunnableToSuspended(kWaitingForDebuggerSend);
    SendBufferedRequest(type, wrapiov);
    self->TransitionFromSuspendedToRunnable();
  } else {
    // Send and possibly block GC...
    SendBufferedRequest(type, wrapiov);
  }
}

}  // namespace JDWP

}  // namespace art
