ART: Add CheckJNI lock checking

JNI MonitorEnter and MonitorExit have similar rules to structured
locking. Count locks in CheckJNI mode.

Bug: 23502994
Change-Id: Ie3f53d3aa669a6bd0c7153c50c168116b43764d9
diff --git a/runtime/jni_env_ext.h b/runtime/jni_env_ext.h
index 9b55536..3828ff0 100644
--- a/runtime/jni_env_ext.h
+++ b/runtime/jni_env_ext.h
@@ -43,8 +43,8 @@
 
   void SetCheckJniEnabled(bool enabled);
 
-  void PushFrame(int capacity);
-  void PopFrame();
+  void PushFrame(int capacity) SHARED_REQUIRES(Locks::mutator_lock_);
+  void PopFrame() SHARED_REQUIRES(Locks::mutator_lock_);
 
   template<typename T>
   T AddLocalReference(mirror::Object* obj)
@@ -89,10 +89,27 @@
   // Used by -Xcheck:jni.
   const JNINativeInterface* unchecked_functions;
 
+  // Functions to keep track of monitor lock and unlock operations. Used to ensure proper locking
+  // rules in CheckJNI mode.
+
+  // Record locking of a monitor.
+  void RecordMonitorEnter(jobject obj) SHARED_REQUIRES(Locks::mutator_lock_);
+
+  // Check the release, that is, that the release is performed in the same JNI "segment."
+  void CheckMonitorRelease(jobject obj) SHARED_REQUIRES(Locks::mutator_lock_);
+
+  // Check that no monitors are held that have been acquired in this JNI "segment."
+  void CheckNoHeldMonitors() SHARED_REQUIRES(Locks::mutator_lock_);
+
  private:
   // The constructor should not be called directly. It may leave the object in an erronuous state,
   // and the result needs to be checked.
   JNIEnvExt(Thread* self, JavaVMExt* vm);
+
+  // All locked objects, with the (Java caller) stack frame that locked them. Used in CheckJNI
+  // to ensure that only monitors locked in this native frame are being unlocked, and that at
+  // the end all are unlocked.
+  std::vector<std::pair<uintptr_t, jobject>> locked_objects_;
 };
 
 // Used to save and restore the JNIEnvExt state when not going through code created by the JNI