Implement ThreadReference.CurrentContendedMonitor and ThreadReference.Interrupt.

The JDWP test for CurrentContendedMonitor also uses Interrupt.

Change-Id: Id1f6add29b578a0494da672d21dd54f23e866475
diff --git a/src/debugger.cc b/src/debugger.cc
index 958fd38..8724327 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -713,6 +713,24 @@
   return JDWP::ERR_NONE;
 }
 
+JDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id, JDWP::ObjectId& contended_monitor)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ScopedObjectAccessUnchecked soa(Thread::Current());
+  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
+  Thread* thread;
+  JDWP::JdwpError error = DecodeThread(soa, thread_id, thread);
+  if (error != JDWP::ERR_NONE) {
+    return error;
+  }
+  if (!IsSuspendedForDebugger(soa, thread)) {
+    return JDWP::ERR_THREAD_NOT_SUSPENDED;
+  }
+
+  contended_monitor = gRegistry->Add(Monitor::GetContendedMonitor(thread));
+
+  return JDWP::ERR_NONE;
+}
+
 JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError status;
   Class* c = DecodeClass(class_id, status);
@@ -1574,6 +1592,18 @@
   return JDWP::ERR_NONE;
 }
 
+JDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) {
+  ScopedObjectAccess soa(Thread::Current());
+  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
+  Thread* thread;
+  JDWP::JdwpError error = DecodeThread(soa, thread_id, thread);
+  if (error != JDWP::ERR_NONE) {
+    return error;
+  }
+  thread->Interrupt();
+  return JDWP::ERR_NONE;
+}
+
 void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId>& thread_ids) {
   class ThreadListVisitor {
    public: