/*
 * 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.
*/

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_REQUIRES(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) {
      break;
    }

    // Execute method.
    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();
  ScopedThreadSuspension sts(self, 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);
  }
}

/*
 * 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 + kJDWPHeaderSizeOffset, expandBufGetLength(pReq));
  Set4BE(buf + kJDWPHeaderIdOffset, NextRequestSerial());
  Set1(buf + kJDWPHeaderFlagsOffset, 0);     /* flags */
  Set1(buf + kJDWPHeaderCmdSetOffset, kJDWPEventCmdSet);
  Set1(buf + kJDWPHeaderCmdOffset, kJDWPEventCompositeCmd);

  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_REQUIRES(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_REQUIRES(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.
    ScopedThreadSuspension sts(self, kWaitingForDebuggerSend);
    SendBufferedRequest(type, wrapiov);
  } else {
    // Send and possibly block GC...
    SendBufferedRequest(type, wrapiov);
  }
}

}  // namespace JDWP

}  // namespace art
