Make native field operations call instrumentation listeners.

Previously native reads and writes of fields would not be reported to
instrumentation listeners.

We filter these events out from the debugger since currently the
debugger will deadlock if it tries to propagate them through JDWP.

Bug: 62712031

Test: ./test.py --host --trace -j40
Test: ./art/tools/run-jdwp-tests.sh --mode=host
Test: Manual
Change-Id: Ibc75248bdca06537d8b4ff7bb890546136ffa161
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 7e70b75..12bdb32 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2927,7 +2927,8 @@
 
 void Dbg::PostFieldAccessEvent(ArtMethod* m, int dex_pc,
                                mirror::Object* this_object, ArtField* f) {
-  if (!IsDebuggerActive()) {
+  // TODO We should send events for native methods.
+  if (!IsDebuggerActive() || m->IsNative()) {
     return;
   }
   DCHECK(m != nullptr);
@@ -2941,7 +2942,8 @@
 void Dbg::PostFieldModificationEvent(ArtMethod* m, int dex_pc,
                                      mirror::Object* this_object, ArtField* f,
                                      const JValue* field_value) {
-  if (!IsDebuggerActive()) {
+  // TODO We should send events for native methods.
+  if (!IsDebuggerActive() || m->IsNative()) {
     return;
   }
   DCHECK(m != nullptr);
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 6be0953..0aabbea 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -40,6 +40,7 @@
 #include "interpreter/interpreter.h"
 #include "jni_env_ext.h"
 #include "java_vm_ext.h"
+#include "jvalue-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/field-inl.h"
@@ -64,6 +65,84 @@
 // things not rendering correctly. E.g. b/16858794
 static constexpr bool kWarnJniAbort = false;
 
+// Helpers to call instrumentation functions for fields. These take jobjects so we don't need to set
+// up handles for the rare case where these actually do something. Once these functions return it is
+// possible there will be a pending exception if the instrumentation happens to throw one.
+static void NotifySetObjectField(ArtField* field, jobject obj, jobject jval)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  DCHECK_EQ(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
+    Thread* self = Thread::Current();
+    ArtMethod* cur_method = self->GetCurrentMethod(/*dex_pc*/ nullptr,
+                                                   /*check_suspended*/ true,
+                                                   /*abort_on_error*/ false);
+
+    if (cur_method == nullptr) {
+      // Set/Get Fields can be issued without a method during runtime startup/teardown. Ignore all
+      // of these changes.
+      return;
+    }
+    DCHECK(cur_method->IsNative());
+    JValue val;
+    val.SetL(self->DecodeJObject(jval));
+    instrumentation->FieldWriteEvent(self,
+                                     self->DecodeJObject(obj).Ptr(),
+                                     cur_method,
+                                     0,  // dex_pc is always 0 since this is a native method.
+                                     field,
+                                     val);
+  }
+}
+
+static void NotifySetPrimitiveField(ArtField* field, jobject obj, JValue val)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  DCHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
+    Thread* self = Thread::Current();
+    ArtMethod* cur_method = self->GetCurrentMethod(/*dex_pc*/ nullptr,
+                                                   /*check_suspended*/ true,
+                                                   /*abort_on_error*/ false);
+
+    if (cur_method == nullptr) {
+      // Set/Get Fields can be issued without a method during runtime startup/teardown. Ignore all
+      // of these changes.
+      return;
+    }
+    DCHECK(cur_method->IsNative());
+    instrumentation->FieldWriteEvent(self,
+                                     self->DecodeJObject(obj).Ptr(),
+                                     cur_method,
+                                     0,  // dex_pc is always 0 since this is a native method.
+                                     field,
+                                     val);
+  }
+}
+
+static void NotifyGetField(ArtField* field, jobject obj)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
+    Thread* self = Thread::Current();
+    ArtMethod* cur_method = self->GetCurrentMethod(/*dex_pc*/ nullptr,
+                                                   /*check_suspended*/ true,
+                                                   /*abort_on_error*/ false);
+
+    if (cur_method == nullptr) {
+      // Set/Get Fields can be issued without a method during runtime startup/teardown. Ignore all
+      // of these changes.
+      return;
+    }
+    DCHECK(cur_method->IsNative());
+    instrumentation->FieldReadEvent(self,
+                                    self->DecodeJObject(obj).Ptr(),
+                                    cur_method,
+                                    0,  // dex_pc is always 0 since this is a native method.
+                                    field);
+  }
+}
+
 // Section 12.3.2 of the JNI spec describes JNI class descriptors. They're
 // separated with slashes but aren't wrapped with "L;" like regular descriptors
 // (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an
@@ -1235,8 +1314,9 @@
     CHECK_NON_NULL_ARGUMENT(obj);
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
-    ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
     ArtField* f = jni::DecodeArtField(fid);
+    NotifyGetField(f, obj);
+    ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
     return soa.AddLocalReference<jobject>(f->GetObject(o));
   }
 
@@ -1244,6 +1324,7 @@
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     ArtField* f = jni::DecodeArtField(fid);
+    NotifyGetField(f, nullptr);
     return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass()));
   }
 
@@ -1251,17 +1332,19 @@
     CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_object);
     CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
     ScopedObjectAccess soa(env);
+    ArtField* f = jni::DecodeArtField(fid);
+    NotifySetObjectField(f, java_object, java_value);
     ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
     ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value);
-    ArtField* f = jni::DecodeArtField(fid);
     f->SetObject<false>(o, v);
   }
 
   static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
     CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid);
     ScopedObjectAccess soa(env);
-    ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value);
     ArtField* f = jni::DecodeArtField(fid);
+    NotifySetObjectField(f, nullptr, java_value);
+    ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value);
     f->SetObject<false>(f->GetDeclaringClass(), v);
   }
 
@@ -1269,28 +1352,32 @@
   CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(instance); \
   CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
   ScopedObjectAccess soa(env); \
-  ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \
   ArtField* f = jni::DecodeArtField(fid); \
+  NotifyGetField(f, instance); \
+  ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \
   return f->Get ##fn (o)
 
 #define GET_STATIC_PRIMITIVE_FIELD(fn) \
   CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \
   ScopedObjectAccess soa(env); \
   ArtField* f = jni::DecodeArtField(fid); \
+  NotifyGetField(f, nullptr); \
   return f->Get ##fn (f->GetDeclaringClass())
 
 #define SET_PRIMITIVE_FIELD(fn, instance, value) \
   CHECK_NON_NULL_ARGUMENT_RETURN_VOID(instance); \
   CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
   ScopedObjectAccess soa(env); \
-  ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \
   ArtField* f = jni::DecodeArtField(fid); \
+  NotifySetPrimitiveField(f, instance, JValue::FromPrimitive<decltype(value)>(value)); \
+  ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \
   f->Set ##fn <false>(o, value)
 
 #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
   CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \
   ScopedObjectAccess soa(env); \
   ArtField* f = jni::DecodeArtField(fid); \
+  NotifySetPrimitiveField(f, nullptr, JValue::FromPrimitive<decltype(value)>(value)); \
   f->Set ##fn <false>(f->GetDeclaringClass(), value)
 
   static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
diff --git a/runtime/jvalue-inl.h b/runtime/jvalue-inl.h
index b33686c..25e34b2 100644
--- a/runtime/jvalue-inl.h
+++ b/runtime/jvalue-inl.h
@@ -27,6 +27,24 @@
   l = new_l.Ptr();
 }
 
+#define DEFINE_FROM(type, chr) \
+    template <> inline JValue JValue::FromPrimitive(type v) { \
+      JValue res; \
+      res.Set ## chr(v); \
+      return res; \
+    }
+
+DEFINE_FROM(uint8_t, Z);
+DEFINE_FROM(int8_t, B);
+DEFINE_FROM(uint16_t, C);
+DEFINE_FROM(int16_t, S);
+DEFINE_FROM(int32_t, I);
+DEFINE_FROM(int64_t, J);
+DEFINE_FROM(float, F);
+DEFINE_FROM(double, D);
+
+#undef DEFINE_FROM
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_JVALUE_INL_H_
diff --git a/runtime/jvalue.h b/runtime/jvalue.h
index f61a07c..266abcf 100644
--- a/runtime/jvalue.h
+++ b/runtime/jvalue.h
@@ -33,6 +33,8 @@
   // We default initialize JValue instances to all-zeros.
   JValue() : j(0) {}
 
+  template<typename T> static JValue FromPrimitive(T v);
+
   int8_t GetB() const { return b; }
   void SetB(int8_t new_b) {
     j = ((static_cast<int64_t>(new_b) << 56) >> 56);  // Sign-extend to 64 bits.