Handler-ize InstrumentationListener and related code

We are going to be making instrumentation listeners that can cause
suspensions during their running. We explicitly handler-ize all the
instrumentation listener functions in order to ensure this is safe.

Bug: 34414073
Test: ./test.py --host --ntrace --trace -j40
Change-Id: Ic719080d0991b104d41b7757df8d1f332c72cd04
diff --git a/runtime/instrumentation_test.cc b/runtime/instrumentation_test.cc
index 9926ee7..2a601c9 100644
--- a/runtime/instrumentation_test.cc
+++ b/runtime/instrumentation_test.cc
@@ -23,11 +23,13 @@
 #include "dex_file.h"
 #include "gc/scoped_gc_critical_section.h"
 #include "handle_scope-inl.h"
+#include "jni_internal.h"
 #include "jvalue.h"
 #include "runtime.h"
 #include "scoped_thread_state_change-inl.h"
 #include "thread_list.h"
-#include "thread-current-inl.h"
+#include "thread-inl.h"
+#include "well_known_classes.h"
 
 namespace art {
 namespace instrumentation {
@@ -35,16 +37,22 @@
 class TestInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
  public:
   TestInstrumentationListener()
-    : received_method_enter_event(false), received_method_exit_event(false),
-      received_method_unwind_event(false), received_dex_pc_moved_event(false),
-      received_field_read_event(false), received_field_written_event(false),
-      received_exception_caught_event(false), received_branch_event(false),
+    : received_method_enter_event(false),
+      received_method_exit_event(false),
+      received_method_exit_object_event(false),
+      received_method_unwind_event(false),
+      received_dex_pc_moved_event(false),
+      received_field_read_event(false),
+      received_field_written_event(false),
+      received_field_written_object_event(false),
+      received_exception_caught_event(false),
+      received_branch_event(false),
       received_invoke_virtual_or_interface_event(false) {}
 
   virtual ~TestInstrumentationListener() {}
 
   void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
-                     mirror::Object* this_object ATTRIBUTE_UNUSED,
+                     Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
                      ArtMethod* method ATTRIBUTE_UNUSED,
                      uint32_t dex_pc ATTRIBUTE_UNUSED)
       OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -52,7 +60,16 @@
   }
 
   void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
-                    mirror::Object* this_object ATTRIBUTE_UNUSED,
+                    Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
+                    ArtMethod* method ATTRIBUTE_UNUSED,
+                    uint32_t dex_pc ATTRIBUTE_UNUSED,
+                    Handle<mirror::Object> return_value ATTRIBUTE_UNUSED)
+      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    received_method_exit_object_event = true;
+  }
+
+  void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
+                    Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
                     ArtMethod* method ATTRIBUTE_UNUSED,
                     uint32_t dex_pc ATTRIBUTE_UNUSED,
                     const JValue& return_value ATTRIBUTE_UNUSED)
@@ -61,7 +78,7 @@
   }
 
   void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
-                    mirror::Object* this_object ATTRIBUTE_UNUSED,
+                    Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
                     ArtMethod* method ATTRIBUTE_UNUSED,
                     uint32_t dex_pc ATTRIBUTE_UNUSED)
       OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -69,7 +86,7 @@
   }
 
   void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
-                  mirror::Object* this_object ATTRIBUTE_UNUSED,
+                  Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
                   ArtMethod* method ATTRIBUTE_UNUSED,
                   uint32_t new_dex_pc ATTRIBUTE_UNUSED)
       OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -77,7 +94,7 @@
   }
 
   void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
-                 mirror::Object* this_object ATTRIBUTE_UNUSED,
+                 Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
                  ArtMethod* method ATTRIBUTE_UNUSED,
                  uint32_t dex_pc ATTRIBUTE_UNUSED,
                  ArtField* field ATTRIBUTE_UNUSED)
@@ -86,7 +103,17 @@
   }
 
   void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
-                    mirror::Object* this_object ATTRIBUTE_UNUSED,
+                    Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
+                    ArtMethod* method ATTRIBUTE_UNUSED,
+                    uint32_t dex_pc ATTRIBUTE_UNUSED,
+                    ArtField* field ATTRIBUTE_UNUSED,
+                    Handle<mirror::Object> field_value ATTRIBUTE_UNUSED)
+      OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+    received_field_written_object_event = true;
+  }
+
+  void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
+                    Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
                     ArtMethod* method ATTRIBUTE_UNUSED,
                     uint32_t dex_pc ATTRIBUTE_UNUSED,
                     ArtField* field ATTRIBUTE_UNUSED,
@@ -96,7 +123,7 @@
   }
 
   void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
-                       mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
+                       Handle<mirror::Throwable> exception_object ATTRIBUTE_UNUSED)
       OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
     received_exception_caught_event = true;
   }
@@ -110,7 +137,7 @@
   }
 
   void InvokeVirtualOrInterface(Thread* thread ATTRIBUTE_UNUSED,
-                                mirror::Object* this_object ATTRIBUTE_UNUSED,
+                                Handle<mirror::Object> this_object ATTRIBUTE_UNUSED,
                                 ArtMethod* caller ATTRIBUTE_UNUSED,
                                 uint32_t dex_pc ATTRIBUTE_UNUSED,
                                 ArtMethod* callee ATTRIBUTE_UNUSED)
@@ -121,10 +148,12 @@
   void Reset() {
     received_method_enter_event = false;
     received_method_exit_event = false;
+    received_method_exit_object_event = false;
     received_method_unwind_event = false;
     received_dex_pc_moved_event = false;
     received_field_read_event = false;
     received_field_written_event = false;
+    received_field_written_object_event = false;
     received_exception_caught_event = false;
     received_branch_event = false;
     received_invoke_virtual_or_interface_event = false;
@@ -132,10 +161,12 @@
 
   bool received_method_enter_event;
   bool received_method_exit_event;
+  bool received_method_exit_object_event;
   bool received_method_unwind_event;
   bool received_dex_pc_moved_event;
   bool received_field_read_event;
   bool received_field_written_event;
+  bool received_field_written_object_event;
   bool received_exception_caught_event;
   bool received_branch_event;
   bool received_invoke_virtual_or_interface_event;
@@ -171,6 +202,13 @@
   }
 
   void TestEvent(uint32_t instrumentation_event) {
+    TestEvent(instrumentation_event, nullptr, nullptr, false);
+  }
+
+  void TestEvent(uint32_t instrumentation_event,
+                 ArtMethod* event_method,
+                 ArtField* event_field,
+                 bool with_object) {
     ScopedObjectAccess soa(Thread::Current());
     instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
     TestInstrumentationListener listener;
@@ -180,15 +218,20 @@
       instr->AddListener(&listener, instrumentation_event);
     }
 
-    ArtMethod* const event_method = nullptr;
     mirror::Object* const event_obj = nullptr;
     const uint32_t event_dex_pc = 0;
 
     // Check the listener is registered and is notified of the event.
     EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
-    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
-    ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
-    EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
+    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
+    ReportEvent(instr,
+                instrumentation_event,
+                soa.Self(),
+                event_method,
+                event_obj,
+                event_field,
+                event_dex_pc);
+    EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
 
     listener.Reset();
     {
@@ -199,9 +242,15 @@
 
     // Check the listener is not registered and is not notified of the event.
     EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
-    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
-    ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
-    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
+    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
+    ReportEvent(instr,
+                instrumentation_event,
+                soa.Self(),
+                event_method,
+                event_obj,
+                event_field,
+                event_dex_pc);
+    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
   }
 
   void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
@@ -317,8 +366,12 @@
     }
   }
 
-  static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
-                          Thread* self, ArtMethod* method, mirror::Object* obj,
+  static void ReportEvent(const instrumentation::Instrumentation* instr,
+                          uint32_t event_type,
+                          Thread* self,
+                          ArtMethod* method,
+                          mirror::Object* obj,
+                          ArtField* field,
                           uint32_t dex_pc)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     switch (event_type) {
@@ -337,11 +390,11 @@
         instr->DexPcMovedEvent(self, obj, method, dex_pc);
         break;
       case instrumentation::Instrumentation::kFieldRead:
-        instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
+        instr->FieldReadEvent(self, obj, method, dex_pc, field);
         break;
       case instrumentation::Instrumentation::kFieldWritten: {
         JValue value;
-        instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
+        instr->FieldWriteEvent(self, obj, method, dex_pc, field, value);
         break;
       }
       case instrumentation::Instrumentation::kExceptionCaught: {
@@ -364,12 +417,14 @@
   }
 
   static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
-                                      uint32_t event_type) {
+                                      uint32_t event_type,
+                                      bool with_object) {
     switch (event_type) {
       case instrumentation::Instrumentation::kMethodEntered:
         return listener.received_method_enter_event;
       case instrumentation::Instrumentation::kMethodExited:
-        return listener.received_method_exit_event;
+        return (!with_object && listener.received_method_exit_event) ||
+            (with_object && listener.received_method_exit_object_event);
       case instrumentation::Instrumentation::kMethodUnwind:
         return listener.received_method_unwind_event;
       case instrumentation::Instrumentation::kDexPcMoved:
@@ -377,7 +432,8 @@
       case instrumentation::Instrumentation::kFieldRead:
         return listener.received_field_read_event;
       case instrumentation::Instrumentation::kFieldWritten:
-        return listener.received_field_written_event;
+        return (!with_object && listener.received_field_written_event) ||
+            (with_object && listener.received_field_written_object_event);
       case instrumentation::Instrumentation::kExceptionCaught:
         return listener.received_exception_caught_event;
       case instrumentation::Instrumentation::kBranch:
@@ -419,8 +475,42 @@
   TestEvent(instrumentation::Instrumentation::kMethodEntered);
 }
 
-TEST_F(InstrumentationTest, MethodExitEvent) {
-  TestEvent(instrumentation::Instrumentation::kMethodExited);
+TEST_F(InstrumentationTest, MethodExitObjectEvent) {
+  ScopedObjectAccess soa(Thread::Current());
+  jobject class_loader = LoadDex("Instrumentation");
+  Runtime* const runtime = Runtime::Current();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
+  mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
+  ASSERT_TRUE(klass != nullptr);
+  ArtMethod* method = klass->FindDeclaredDirectMethod("returnReference",
+                                                      "()Ljava/lang/Object;",
+                                                      kRuntimePointerSize);
+  ASSERT_TRUE(method != nullptr);
+  TestEvent(instrumentation::Instrumentation::kMethodExited,
+            /*event_method*/ method,
+            /*event_field*/ nullptr,
+            /*with_object*/ true);
+}
+
+TEST_F(InstrumentationTest, MethodExitPrimEvent) {
+  ScopedObjectAccess soa(Thread::Current());
+  jobject class_loader = LoadDex("Instrumentation");
+  Runtime* const runtime = Runtime::Current();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
+  mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
+  ASSERT_TRUE(klass != nullptr);
+  ArtMethod* method = klass->FindDeclaredDirectMethod("returnPrimitive",
+                                                      "()I",
+                                                      kRuntimePointerSize);
+  ASSERT_TRUE(method != nullptr);
+  TestEvent(instrumentation::Instrumentation::kMethodExited,
+            /*event_method*/ method,
+            /*event_field*/ nullptr,
+            /*with_object*/ false);
 }
 
 TEST_F(InstrumentationTest, MethodUnwindEvent) {
@@ -435,8 +525,40 @@
   TestEvent(instrumentation::Instrumentation::kFieldRead);
 }
 
-TEST_F(InstrumentationTest, FieldWriteEvent) {
-  TestEvent(instrumentation::Instrumentation::kFieldWritten);
+TEST_F(InstrumentationTest, FieldWriteObjectEvent) {
+  ScopedObjectAccess soa(Thread::Current());
+  jobject class_loader = LoadDex("Instrumentation");
+  Runtime* const runtime = Runtime::Current();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
+  mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
+  ASSERT_TRUE(klass != nullptr);
+  ArtField* field = klass->FindDeclaredStaticField("referenceField", "Ljava/lang/Object;");
+  ASSERT_TRUE(field != nullptr);
+
+  TestEvent(instrumentation::Instrumentation::kFieldWritten,
+            /*event_method*/ nullptr,
+            /*event_field*/ field,
+            /*with_object*/ true);
+}
+
+TEST_F(InstrumentationTest, FieldWritePrimEvent) {
+  ScopedObjectAccess soa(Thread::Current());
+  jobject class_loader = LoadDex("Instrumentation");
+  Runtime* const runtime = Runtime::Current();
+  ClassLinker* class_linker = runtime->GetClassLinker();
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
+  mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
+  ASSERT_TRUE(klass != nullptr);
+  ArtField* field = klass->FindDeclaredStaticField("primitiveField", "I");
+  ASSERT_TRUE(field != nullptr);
+
+  TestEvent(instrumentation::Instrumentation::kFieldWritten,
+            /*event_method*/ nullptr,
+            /*event_field*/ field,
+            /*with_object*/ false);
 }
 
 TEST_F(InstrumentationTest, ExceptionCaughtEvent) {