Implement JDWP InvokeMethod and breakpoints on exception throwing.

Change-Id: I1142bee843104f0850fd7270752104d5d73a44f0
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index b628e6c..36e2657 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -31,6 +31,7 @@
 
 namespace art {
 
+struct Method;
 struct Thread;
 
 namespace JDWP {
@@ -56,6 +57,7 @@
 static inline RefTypeId ReadRefTypeId(const uint8_t** pBuf) { return Read8BE(pBuf); }
 static inline FrameId ReadFrameId(const uint8_t** pBuf) { return Read8BE(pBuf); }
 static inline JdwpTag ReadTag(const uint8_t** pBuf) { return static_cast<JdwpTag>(Read1(pBuf)); }
+static inline JdwpTypeTag ReadTypeTag(const uint8_t** pBuf) { return static_cast<JdwpTypeTag>(Read1(pBuf)); }
 static inline void SetFieldId(uint8_t* buf, FieldId val) { return Set4BE(buf, val); }
 static inline void SetMethodId(uint8_t* buf, MethodId val) { return Set4BE(buf, val); }
 static inline void SetObjectId(uint8_t* buf, ObjectId val) { return Set8BE(buf, val); }
@@ -71,10 +73,10 @@
  * Holds a JDWP "location".
  */
 struct JdwpLocation {
-  uint8_t typeTag;        /* class or interface? */
-  RefTypeId classId;        /* method->clazz */
-  MethodId methodId;       /* method in which "idx" resides */
-  uint64_t idx;            /* relative index into code block */
+  JdwpTypeTag typeTag;
+  RefTypeId classId;
+  MethodId methodId;
+  uint64_t idx; // A Dex PC.
 };
 std::ostream& operator<<(std::ostream& os, const JdwpLocation& rhs);
 
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 15e1151..424d87f 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -535,7 +535,7 @@
      * The JDWP thread has told us (and possibly all other threads) to
      * resume.  See if it has left anything in our DebugInvokeReq mailbox.
      */
-    if (!pReq->invoke_needed) {
+    if (!pReq->invoke_needed_) {
       /*LOGD("SuspendByPolicy: no invoke needed");*/
       break;
     }
@@ -543,14 +543,14 @@
     /* grab this before posting/suspending again */
     SetWaitForEventThread(Dbg::GetThreadSelfId());
 
-    /* leave pReq->invoke_needed raised so we can check reentrancy */
+    /* leave pReq->invoke_needed_ raised so we can check reentrancy */
     LOG(VERBOSE) << "invoking method...";
     Dbg::ExecuteMethod(pReq);
 
     pReq->error = ERR_NONE;
 
     /* clear this before signaling */
-    pReq->invoke_needed = false;
+    pReq->invoke_needed_ = false;
 
     LOG(VERBOSE) << "invoke complete, signaling and self-suspending";
     MutexLock mu(pReq->lock_);
@@ -567,7 +567,7 @@
  */
 bool JdwpState::InvokeInProgress() {
   DebugInvokeReq* pReq = Dbg::GetInvokeReq();
-  return pReq->invoke_needed;
+  return pReq->invoke_needed_;
 }
 
 /*
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 9b5c080..238775e 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -49,7 +49,7 @@
  */
 static void jdwpReadLocation(const uint8_t** pBuf, JdwpLocation* pLoc) {
   memset(pLoc, 0, sizeof(*pLoc));     /* allows memcmp() later */
-  pLoc->typeTag = Read1(pBuf);
+  pLoc->typeTag = ReadTypeTag(pBuf);
   pLoc->classId = ReadObjectId(pBuf);
   pLoc->methodId = ReadMethodId(pBuf);
   pLoc->idx = Read8BE(pBuf);
@@ -1467,16 +1467,16 @@
  * Returns the value of "this" for the specified frame.
  */
 static JdwpError handleSF_ThisObject(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
-  ObjectId threadId = ReadObjectId(&buf);
+  ReadObjectId(&buf); // Skip thread id.
   FrameId frameId = ReadFrameId(&buf);
 
   ObjectId objectId;
-  if (!Dbg::GetThisObject(threadId, frameId, &objectId)) {
+  if (!Dbg::GetThisObject(frameId, &objectId)) {
     return ERR_INVALID_FRAMEID;
   }
 
   uint8_t objectTag = Dbg::GetObjectTag(objectId);
-  LOG(VERBOSE) << StringPrintf("  Req for 'this' in thread=%llx frame=%llx --> %llx '%c'", threadId, frameId, objectId, (char)objectTag);
+  LOG(VERBOSE) << StringPrintf("  Req for 'this' in frame=%llx --> %llx '%c'", frameId, objectId, (char)objectTag);
 
   expandBufAdd1(pReply, objectTag);
   expandBufAddObjectId(pReply, objectId);
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index 07ffc52..98490e2 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -451,9 +451,9 @@
 }
 
 std::ostream& operator<<(std::ostream& os, const JdwpLocation& rhs) {
-  // TODO: do we really want the Class* and Method* as pointers?
-  os << rhs.typeTag << " " << (void*) rhs.classId << " " << (void*) rhs.methodId << " " << rhs.idx
-     << " (" << Dbg::GetClassDescriptor(rhs.classId) << "." << Dbg::GetMethodName(rhs.classId, rhs.methodId) << ")";
+  os << "JdwpLocation["
+     << Dbg::GetClassDescriptor(rhs.classId) << "." << Dbg::GetMethodName(rhs.classId, rhs.methodId)
+     << "@" << rhs.idx << " " << rhs.typeTag << "]";
   return os;
 }
 
@@ -481,6 +481,17 @@
   return os;
 }
 
+std::ostream& operator<<(std::ostream& os, const JdwpTypeTag& value) {
+  switch (value) {
+  case TT_CLASS: os << "TT_CLASS"; break;
+  case TT_INTERFACE: os << "TT_INTERFACE"; break;
+  case TT_ARRAY: os << "TT_ARRAY"; break;
+  default:
+    os << "JdwpTypeTag[" << static_cast<int32_t>(value) << "]";
+  }
+  return os;
+}
+
 }  // namespace JDWP
 
 }  // namespace art