1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "instrumentation.h"
18 
19 #include "android-base/macros.h"
20 #include "art_method-inl.h"
21 #include "base/pointer_size.h"
22 #include "class_linker-inl.h"
23 #include "common_runtime_test.h"
24 #include "common_throws.h"
25 #include "dex/dex_file.h"
26 #include "gc/scoped_gc_critical_section.h"
27 #include "handle_scope-inl.h"
28 #include "jni/jni_internal.h"
29 #include "jvalue.h"
30 #include "runtime.h"
31 #include "scoped_thread_state_change-inl.h"
32 #include "interpreter/shadow_frame.h"
33 #include "thread-inl.h"
34 #include "thread_list.h"
35 #include "well_known_classes.h"
36 
37 namespace art HIDDEN {
38 namespace instrumentation {
39 
40 class TestInstrumentationListener final : public instrumentation::InstrumentationListener {
41  public:
TestInstrumentationListener()42   TestInstrumentationListener()
43     : received_method_enter_event(false),
44       received_method_exit_event(false),
45       received_method_exit_object_event(false),
46       received_method_unwind_event(false),
47       received_dex_pc_moved_event(false),
48       received_field_read_event(false),
49       received_field_written_event(false),
50       received_field_written_object_event(false),
51       received_exception_thrown_event(false),
52       received_exception_handled_event(false),
53       received_branch_event(false),
54       received_watched_frame_pop(false) {}
55 
~TestInstrumentationListener()56   virtual ~TestInstrumentationListener() {}
57 
MethodEntered(Thread * thread,ArtMethod * method)58   void MethodEntered([[maybe_unused]] Thread* thread, [[maybe_unused]] ArtMethod* method) override
59       REQUIRES_SHARED(Locks::mutator_lock_) {
60     received_method_enter_event = true;
61   }
62 
MethodExited(Thread * thread,ArtMethod * method,instrumentation::OptionalFrame frame,MutableHandle<mirror::Object> & return_value)63   void MethodExited([[maybe_unused]] Thread* thread,
64                     [[maybe_unused]] ArtMethod* method,
65                     [[maybe_unused]] instrumentation::OptionalFrame frame,
66                     [[maybe_unused]] MutableHandle<mirror::Object>& return_value) override
67       REQUIRES_SHARED(Locks::mutator_lock_) {
68     received_method_exit_object_event = true;
69   }
70 
MethodExited(Thread * thread,ArtMethod * method,instrumentation::OptionalFrame frame,JValue & return_value)71   void MethodExited([[maybe_unused]] Thread* thread,
72                     [[maybe_unused]] ArtMethod* method,
73                     [[maybe_unused]] instrumentation::OptionalFrame frame,
74                     [[maybe_unused]] JValue& return_value) override
75       REQUIRES_SHARED(Locks::mutator_lock_) {
76     received_method_exit_event = true;
77   }
78 
MethodUnwind(Thread * thread,ArtMethod * method,uint32_t dex_pc)79   void MethodUnwind([[maybe_unused]] Thread* thread,
80                     [[maybe_unused]] ArtMethod* method,
81                     [[maybe_unused]] uint32_t dex_pc) override
82       REQUIRES_SHARED(Locks::mutator_lock_) {
83     received_method_unwind_event = true;
84   }
85 
DexPcMoved(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t new_dex_pc)86   void DexPcMoved([[maybe_unused]] Thread* thread,
87                   [[maybe_unused]] Handle<mirror::Object> this_object,
88                   [[maybe_unused]] ArtMethod* method,
89                   [[maybe_unused]] uint32_t new_dex_pc) override
90       REQUIRES_SHARED(Locks::mutator_lock_) {
91     received_dex_pc_moved_event = true;
92   }
93 
FieldRead(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field)94   void FieldRead([[maybe_unused]] Thread* thread,
95                  [[maybe_unused]] Handle<mirror::Object> this_object,
96                  [[maybe_unused]] ArtMethod* method,
97                  [[maybe_unused]] uint32_t dex_pc,
98                  [[maybe_unused]] ArtField* field) override REQUIRES_SHARED(Locks::mutator_lock_) {
99     received_field_read_event = true;
100   }
101 
FieldWritten(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field,Handle<mirror::Object> field_value)102   void FieldWritten([[maybe_unused]] Thread* thread,
103                     [[maybe_unused]] Handle<mirror::Object> this_object,
104                     [[maybe_unused]] ArtMethod* method,
105                     [[maybe_unused]] uint32_t dex_pc,
106                     [[maybe_unused]] ArtField* field,
107                     [[maybe_unused]] Handle<mirror::Object> field_value) override
108       REQUIRES_SHARED(Locks::mutator_lock_) {
109     received_field_written_object_event = true;
110   }
111 
FieldWritten(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field,const JValue & field_value)112   void FieldWritten([[maybe_unused]] Thread* thread,
113                     [[maybe_unused]] Handle<mirror::Object> this_object,
114                     [[maybe_unused]] ArtMethod* method,
115                     [[maybe_unused]] uint32_t dex_pc,
116                     [[maybe_unused]] ArtField* field,
117                     [[maybe_unused]] const JValue& field_value) override
118       REQUIRES_SHARED(Locks::mutator_lock_) {
119     received_field_written_event = true;
120   }
121 
ExceptionThrown(Thread * thread,Handle<mirror::Throwable> exception_object)122   void ExceptionThrown([[maybe_unused]] Thread* thread,
123                        [[maybe_unused]] Handle<mirror::Throwable> exception_object) override
124       REQUIRES_SHARED(Locks::mutator_lock_) {
125     received_exception_thrown_event = true;
126   }
127 
ExceptionHandled(Thread * self,Handle<mirror::Throwable> throwable)128   void ExceptionHandled([[maybe_unused]] Thread* self,
129                         [[maybe_unused]] Handle<mirror::Throwable> throwable) override
130       REQUIRES_SHARED(Locks::mutator_lock_) {
131     received_exception_handled_event = true;
132   }
133 
Branch(Thread * thread,ArtMethod * method,uint32_t dex_pc,int32_t dex_pc_offset)134   void Branch([[maybe_unused]] Thread* thread,
135               [[maybe_unused]] ArtMethod* method,
136               [[maybe_unused]] uint32_t dex_pc,
137               [[maybe_unused]] int32_t dex_pc_offset) override
138       REQUIRES_SHARED(Locks::mutator_lock_) {
139     received_branch_event = true;
140   }
141 
WatchedFramePop(Thread * thread,const ShadowFrame & frame)142   void WatchedFramePop([[maybe_unused]] Thread* thread,
143                        [[maybe_unused]] const ShadowFrame& frame) override
144       REQUIRES_SHARED(Locks::mutator_lock_) {
145     received_watched_frame_pop  = true;
146   }
147 
Reset()148   void Reset() {
149     received_method_enter_event = false;
150     received_method_exit_event = false;
151     received_method_exit_object_event = false;
152     received_method_unwind_event = false;
153     received_dex_pc_moved_event = false;
154     received_field_read_event = false;
155     received_field_written_event = false;
156     received_field_written_object_event = false;
157     received_exception_thrown_event = false;
158     received_exception_handled_event = false;
159     received_branch_event = false;
160     received_watched_frame_pop = false;
161   }
162 
163   bool received_method_enter_event;
164   bool received_method_exit_event;
165   bool received_method_exit_object_event;
166   bool received_method_unwind_event;
167   bool received_dex_pc_moved_event;
168   bool received_field_read_event;
169   bool received_field_written_event;
170   bool received_field_written_object_event;
171   bool received_exception_thrown_event;
172   bool received_exception_handled_event;
173   bool received_branch_event;
174   bool received_watched_frame_pop;
175 
176  private:
177   DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
178 };
179 
180 class InstrumentationTest : public CommonRuntimeTest {
181  public:
182   // Unique keys used to test Instrumentation::ConfigureStubs.
183   static constexpr const char* kClientOneKey = "TestClient1";
184   static constexpr const char* kClientTwoKey = "TestClient2";
185 
InstrumentationTest()186   InstrumentationTest() {
187     use_boot_image_ = true;  // Make the Runtime creation cheaper.
188   }
189 
CheckConfigureStubs(const char * key,Instrumentation::InstrumentationLevel level)190   void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
191     ScopedObjectAccess soa(Thread::Current());
192     instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
193     ScopedThreadSuspension sts(soa.Self(), ThreadState::kSuspended);
194     gc::ScopedGCCriticalSection gcs(soa.Self(),
195                                     gc::kGcCauseInstrumentation,
196                                     gc::kCollectorTypeInstrumentation);
197     ScopedSuspendAll ssa("Instrumentation::ConfigureStubs");
198     instr->ConfigureStubs(key, level, /*try_switch_to_non_debuggable=*/false);
199   }
200 
GetCurrentInstrumentationLevel()201   Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
202     return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
203   }
204 
GetInstrumentationUserCount()205   size_t GetInstrumentationUserCount() {
206     ScopedObjectAccess soa(Thread::Current());
207     return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
208   }
209 
TestEvent(uint32_t instrumentation_event)210   void TestEvent(uint32_t instrumentation_event) {
211     TestEvent(instrumentation_event, nullptr, nullptr, false);
212   }
213 
TestEvent(uint32_t instrumentation_event,ArtMethod * event_method,ArtField * event_field,bool with_object)214   void TestEvent(uint32_t instrumentation_event,
215                  ArtMethod* event_method,
216                  ArtField* event_field,
217                  bool with_object) {
218     ScopedObjectAccess soa(Thread::Current());
219     instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
220     TestInstrumentationListener listener;
221     {
222       ScopedThreadSuspension sts(soa.Self(), ThreadState::kSuspended);
223       ScopedSuspendAll ssa("Add instrumentation listener");
224       instr->AddListener(&listener, instrumentation_event);
225     }
226 
227     mirror::Object* const event_obj = nullptr;
228     const uint32_t event_dex_pc = 0;
229     ShadowFrameAllocaUniquePtr test_frame = CREATE_SHADOW_FRAME(0, event_method, 0);
230 
231     // Check the listener is registered and is notified of the event.
232     EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
233     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
234     ReportEvent(instr,
235                 instrumentation_event,
236                 soa.Self(),
237                 event_method,
238                 event_obj,
239                 event_field,
240                 event_dex_pc,
241                 *test_frame);
242     EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
243 
244     listener.Reset();
245     {
246       ScopedThreadSuspension sts(soa.Self(), ThreadState::kSuspended);
247       ScopedSuspendAll ssa("Remove instrumentation listener");
248       instr->RemoveListener(&listener, instrumentation_event);
249     }
250 
251     // Check the listener is not registered and is not notified of the event.
252     EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
253     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
254     ReportEvent(instr,
255                 instrumentation_event,
256                 soa.Self(),
257                 event_method,
258                 event_obj,
259                 event_field,
260                 event_dex_pc,
261                 *test_frame);
262     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
263   }
264 
DeoptimizeMethod(Thread * self,ArtMethod * method)265   void DeoptimizeMethod(Thread* self, ArtMethod* method)
266       REQUIRES_SHARED(Locks::mutator_lock_) {
267     Runtime* runtime = Runtime::Current();
268     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
269     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
270     gc::ScopedGCCriticalSection gcs(self,
271                                     gc::kGcCauseInstrumentation,
272                                     gc::kCollectorTypeInstrumentation);
273     ScopedSuspendAll ssa("Single method deoptimization");
274     instrumentation->Deoptimize(method);
275   }
276 
UndeoptimizeMethod(Thread * self,ArtMethod * method,const char * key,bool disable_deoptimization)277   void UndeoptimizeMethod(Thread* self, ArtMethod* method,
278                           const char* key, bool disable_deoptimization)
279       REQUIRES_SHARED(Locks::mutator_lock_) {
280     Runtime* runtime = Runtime::Current();
281     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
282     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
283     gc::ScopedGCCriticalSection gcs(self,
284                                     gc::kGcCauseInstrumentation,
285                                     gc::kCollectorTypeInstrumentation);
286     ScopedSuspendAll ssa("Single method undeoptimization");
287     instrumentation->Undeoptimize(method);
288     if (disable_deoptimization) {
289       instrumentation->DisableDeoptimization(key, /*try_switch_to_non_debuggable=*/false);
290     }
291   }
292 
DeoptimizeEverything(Thread * self,const char * key)293   void DeoptimizeEverything(Thread* self, const char* key)
294         REQUIRES_SHARED(Locks::mutator_lock_) {
295     Runtime* runtime = Runtime::Current();
296     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
297     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
298     gc::ScopedGCCriticalSection gcs(self,
299                                     gc::kGcCauseInstrumentation,
300                                     gc::kCollectorTypeInstrumentation);
301     ScopedSuspendAll ssa("Full deoptimization");
302     instrumentation->DeoptimizeEverything(key);
303   }
304 
UndeoptimizeEverything(Thread * self,const char * key,bool disable_deoptimization)305   void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
306         REQUIRES_SHARED(Locks::mutator_lock_) {
307     Runtime* runtime = Runtime::Current();
308     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
309     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
310     gc::ScopedGCCriticalSection gcs(self,
311                                     gc::kGcCauseInstrumentation,
312                                     gc::kCollectorTypeInstrumentation);
313     ScopedSuspendAll ssa("Full undeoptimization");
314     instrumentation->UndeoptimizeEverything(key);
315     if (disable_deoptimization) {
316       instrumentation->DisableDeoptimization(key, /*try_switch_to_non_debuggable=*/false);
317     }
318   }
319 
EnableMethodTracing(Thread * self,const char * key,bool needs_interpreter)320   void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
321         REQUIRES_SHARED(Locks::mutator_lock_) {
322     Runtime* runtime = Runtime::Current();
323     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
324     TestInstrumentationListener listener;
325     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
326     gc::ScopedGCCriticalSection gcs(self,
327                                     gc::kGcCauseInstrumentation,
328                                     gc::kCollectorTypeInstrumentation);
329     ScopedSuspendAll ssa("EnableMethodTracing");
330     instrumentation->EnableMethodTracing(key, &listener, needs_interpreter);
331   }
332 
DisableMethodTracing(Thread * self,const char * key)333   void DisableMethodTracing(Thread* self, const char* key)
334         REQUIRES_SHARED(Locks::mutator_lock_) {
335     Runtime* runtime = Runtime::Current();
336     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
337     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
338     gc::ScopedGCCriticalSection gcs(self,
339                                     gc::kGcCauseInstrumentation,
340                                     gc::kCollectorTypeInstrumentation);
341     ScopedSuspendAll ssa("EnableMethodTracing");
342     instrumentation->DisableMethodTracing(key);
343   }
344 
345  private:
HasEventListener(const instrumentation::Instrumentation * instr,uint32_t event_type)346   static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
347       REQUIRES_SHARED(Locks::mutator_lock_) {
348     switch (event_type) {
349       case instrumentation::Instrumentation::kMethodEntered:
350         return instr->HasMethodEntryListeners();
351       case instrumentation::Instrumentation::kMethodExited:
352         return instr->HasMethodExitListeners();
353       case instrumentation::Instrumentation::kMethodUnwind:
354         return instr->HasMethodUnwindListeners();
355       case instrumentation::Instrumentation::kDexPcMoved:
356         return instr->HasDexPcListeners();
357       case instrumentation::Instrumentation::kFieldRead:
358         return instr->HasFieldReadListeners();
359       case instrumentation::Instrumentation::kFieldWritten:
360         return instr->HasFieldWriteListeners();
361       case instrumentation::Instrumentation::kExceptionThrown:
362         return instr->HasExceptionThrownListeners();
363       case instrumentation::Instrumentation::kExceptionHandled:
364         return instr->HasExceptionHandledListeners();
365       case instrumentation::Instrumentation::kBranch:
366         return instr->HasBranchListeners();
367       case instrumentation::Instrumentation::kWatchedFramePop:
368         return instr->HasWatchedFramePopListeners();
369       default:
370         LOG(FATAL) << "Unknown instrumentation event " << event_type;
371         UNREACHABLE();
372     }
373   }
374 
ReportEvent(const instrumentation::Instrumentation * instr,uint32_t event_type,Thread * self,ArtMethod * method,mirror::Object * obj,ArtField * field,uint32_t dex_pc,const ShadowFrame & frame)375   static void ReportEvent(const instrumentation::Instrumentation* instr,
376                           uint32_t event_type,
377                           Thread* self,
378                           ArtMethod* method,
379                           mirror::Object* obj,
380                           ArtField* field,
381                           uint32_t dex_pc,
382                           const ShadowFrame& frame)
383       REQUIRES_SHARED(Locks::mutator_lock_) {
384     switch (event_type) {
385       case instrumentation::Instrumentation::kMethodEntered:
386         instr->MethodEnterEvent(self, method);
387         break;
388       case instrumentation::Instrumentation::kMethodExited: {
389         JValue value;
390         instr->MethodExitEvent(self, method, {}, value);
391         break;
392       }
393       case instrumentation::Instrumentation::kMethodUnwind:
394         instr->MethodUnwindEvent(self, method, dex_pc);
395         break;
396       case instrumentation::Instrumentation::kDexPcMoved:
397         instr->DexPcMovedEvent(self, obj, method, dex_pc);
398         break;
399       case instrumentation::Instrumentation::kFieldRead:
400         instr->FieldReadEvent(self, obj, method, dex_pc, field);
401         break;
402       case instrumentation::Instrumentation::kFieldWritten: {
403         JValue value;
404         instr->FieldWriteEvent(self, obj, method, dex_pc, field, value);
405         break;
406       }
407       case instrumentation::Instrumentation::kExceptionThrown: {
408         ThrowArithmeticExceptionDivideByZero();
409         mirror::Throwable* event_exception = self->GetException();
410         instr->ExceptionThrownEvent(self, event_exception);
411         self->ClearException();
412         break;
413       }
414       case instrumentation::Instrumentation::kBranch:
415         instr->Branch(self, method, dex_pc, -1);
416         break;
417       case instrumentation::Instrumentation::kWatchedFramePop:
418         instr->WatchedFramePopped(self, frame);
419         break;
420       case instrumentation::Instrumentation::kExceptionHandled: {
421         ThrowArithmeticExceptionDivideByZero();
422         mirror::Throwable* event_exception = self->GetException();
423         self->ClearException();
424         instr->ExceptionHandledEvent(self, event_exception);
425         break;
426       }
427       default:
428         LOG(FATAL) << "Unknown instrumentation event " << event_type;
429         UNREACHABLE();
430     }
431   }
432 
DidListenerReceiveEvent(const TestInstrumentationListener & listener,uint32_t event_type,bool with_object)433   static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
434                                       uint32_t event_type,
435                                       bool with_object) {
436     switch (event_type) {
437       case instrumentation::Instrumentation::kMethodEntered:
438         return listener.received_method_enter_event;
439       case instrumentation::Instrumentation::kMethodExited:
440         return (!with_object && listener.received_method_exit_event) ||
441             (with_object && listener.received_method_exit_object_event);
442       case instrumentation::Instrumentation::kMethodUnwind:
443         return listener.received_method_unwind_event;
444       case instrumentation::Instrumentation::kDexPcMoved:
445         return listener.received_dex_pc_moved_event;
446       case instrumentation::Instrumentation::kFieldRead:
447         return listener.received_field_read_event;
448       case instrumentation::Instrumentation::kFieldWritten:
449         return (!with_object && listener.received_field_written_event) ||
450             (with_object && listener.received_field_written_object_event);
451       case instrumentation::Instrumentation::kExceptionThrown:
452         return listener.received_exception_thrown_event;
453       case instrumentation::Instrumentation::kExceptionHandled:
454         return listener.received_exception_handled_event;
455       case instrumentation::Instrumentation::kBranch:
456         return listener.received_branch_event;
457       case instrumentation::Instrumentation::kWatchedFramePop:
458         return listener.received_watched_frame_pop;
459       default:
460         LOG(FATAL) << "Unknown instrumentation event " << event_type;
461         UNREACHABLE();
462     }
463   }
464 };
465 
TEST_F(InstrumentationTest,NoInstrumentation)466 TEST_F(InstrumentationTest, NoInstrumentation) {
467   ScopedObjectAccess soa(Thread::Current());
468   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
469   ASSERT_NE(instr, nullptr);
470 
471   EXPECT_FALSE(instr->RunExitHooks());
472   EXPECT_FALSE(instr->EntryExitStubsInstalled());
473   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
474   EXPECT_FALSE(instr->NeedsSlowInterpreterForListeners());
475 
476   // Check there is no registered listener.
477   EXPECT_FALSE(instr->HasDexPcListeners());
478   EXPECT_FALSE(instr->HasExceptionThrownListeners());
479   EXPECT_FALSE(instr->HasExceptionHandledListeners());
480   EXPECT_FALSE(instr->HasFieldReadListeners());
481   EXPECT_FALSE(instr->HasFieldWriteListeners());
482   EXPECT_FALSE(instr->HasMethodEntryListeners());
483   EXPECT_FALSE(instr->HasMethodExitListeners());
484 }
485 
486 // Test instrumentation listeners for each event.
TEST_F(InstrumentationTest,MethodEntryEvent)487 TEST_F(InstrumentationTest, MethodEntryEvent) {
488   ScopedObjectAccess soa(Thread::Current());
489   jobject class_loader = LoadDex("Instrumentation");
490   Runtime* const runtime = Runtime::Current();
491   ClassLinker* class_linker = runtime->GetClassLinker();
492   StackHandleScope<1> hs(soa.Self());
493   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
494   ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
495   ASSERT_TRUE(klass != nullptr);
496   ArtMethod* method =
497       klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize);
498   ASSERT_TRUE(method != nullptr);
499   ASSERT_TRUE(method->IsDirect());
500   ASSERT_TRUE(method->GetDeclaringClass() == klass);
501   TestEvent(instrumentation::Instrumentation::kMethodEntered,
502             /*event_method=*/ method,
503             /*event_field=*/ nullptr,
504             /*with_object=*/ true);
505 }
506 
TEST_F(InstrumentationTest,MethodExitObjectEvent)507 TEST_F(InstrumentationTest, MethodExitObjectEvent) {
508   ScopedObjectAccess soa(Thread::Current());
509   jobject class_loader = LoadDex("Instrumentation");
510   Runtime* const runtime = Runtime::Current();
511   ClassLinker* class_linker = runtime->GetClassLinker();
512   StackHandleScope<1> hs(soa.Self());
513   MutableHandle<mirror::ClassLoader> loader(
514       hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
515   ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
516   ASSERT_TRUE(klass != nullptr);
517   ArtMethod* method =
518       klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize);
519   ASSERT_TRUE(method != nullptr);
520   ASSERT_TRUE(method->IsDirect());
521   ASSERT_TRUE(method->GetDeclaringClass() == klass);
522   TestEvent(instrumentation::Instrumentation::kMethodExited,
523             /*event_method=*/ method,
524             /*event_field=*/ nullptr,
525             /*with_object=*/ true);
526 }
527 
TEST_F(InstrumentationTest,MethodExitPrimEvent)528 TEST_F(InstrumentationTest, MethodExitPrimEvent) {
529   ScopedObjectAccess soa(Thread::Current());
530   jobject class_loader = LoadDex("Instrumentation");
531   Runtime* const runtime = Runtime::Current();
532   ClassLinker* class_linker = runtime->GetClassLinker();
533   StackHandleScope<1> hs(soa.Self());
534   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
535   ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
536   ASSERT_TRUE(klass != nullptr);
537   ArtMethod* method = klass->FindClassMethod("returnPrimitive", "()I", kRuntimePointerSize);
538   ASSERT_TRUE(method != nullptr);
539   ASSERT_TRUE(method->IsDirect());
540   ASSERT_TRUE(method->GetDeclaringClass() == klass);
541   TestEvent(instrumentation::Instrumentation::kMethodExited,
542             /*event_method=*/ method,
543             /*event_field=*/ nullptr,
544             /*with_object=*/ false);
545 }
546 
TEST_F(InstrumentationTest,MethodUnwindEvent)547 TEST_F(InstrumentationTest, MethodUnwindEvent) {
548   TestEvent(instrumentation::Instrumentation::kMethodUnwind);
549 }
550 
TEST_F(InstrumentationTest,DexPcMovedEvent)551 TEST_F(InstrumentationTest, DexPcMovedEvent) {
552   TestEvent(instrumentation::Instrumentation::kDexPcMoved);
553 }
554 
TEST_F(InstrumentationTest,FieldReadEvent)555 TEST_F(InstrumentationTest, FieldReadEvent) {
556   TestEvent(instrumentation::Instrumentation::kFieldRead);
557 }
558 
TEST_F(InstrumentationTest,WatchedFramePop)559 TEST_F(InstrumentationTest, WatchedFramePop) {
560   TestEvent(instrumentation::Instrumentation::kWatchedFramePop);
561 }
562 
TEST_F(InstrumentationTest,FieldWriteObjectEvent)563 TEST_F(InstrumentationTest, FieldWriteObjectEvent) {
564   ScopedObjectAccess soa(Thread::Current());
565   jobject class_loader = LoadDex("Instrumentation");
566   Runtime* const runtime = Runtime::Current();
567   ClassLinker* class_linker = runtime->GetClassLinker();
568   StackHandleScope<1> hs(soa.Self());
569   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
570   ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
571   ASSERT_TRUE(klass != nullptr);
572   ArtField* field = klass->FindDeclaredStaticField("referenceField", "Ljava/lang/Object;");
573   ASSERT_TRUE(field != nullptr);
574 
575   TestEvent(instrumentation::Instrumentation::kFieldWritten,
576             /*event_method=*/ nullptr,
577             /*event_field=*/ field,
578             /*with_object=*/ true);
579 }
580 
TEST_F(InstrumentationTest,FieldWritePrimEvent)581 TEST_F(InstrumentationTest, FieldWritePrimEvent) {
582   ScopedObjectAccess soa(Thread::Current());
583   jobject class_loader = LoadDex("Instrumentation");
584   Runtime* const runtime = Runtime::Current();
585   ClassLinker* class_linker = runtime->GetClassLinker();
586   StackHandleScope<1> hs(soa.Self());
587   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
588   ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
589   ASSERT_TRUE(klass != nullptr);
590   ArtField* field = klass->FindDeclaredStaticField("primitiveField", "I");
591   ASSERT_TRUE(field != nullptr);
592 
593   TestEvent(instrumentation::Instrumentation::kFieldWritten,
594             /*event_method=*/ nullptr,
595             /*event_field=*/ field,
596             /*with_object=*/ false);
597 }
598 
TEST_F(InstrumentationTest,ExceptionHandledEvent)599 TEST_F(InstrumentationTest, ExceptionHandledEvent) {
600   TestEvent(instrumentation::Instrumentation::kExceptionHandled);
601 }
602 
TEST_F(InstrumentationTest,ExceptionThrownEvent)603 TEST_F(InstrumentationTest, ExceptionThrownEvent) {
604   TestEvent(instrumentation::Instrumentation::kExceptionThrown);
605 }
606 
TEST_F(InstrumentationTest,BranchEvent)607 TEST_F(InstrumentationTest, BranchEvent) {
608   TestEvent(instrumentation::Instrumentation::kBranch);
609 }
610 
TEST_F(InstrumentationTest,DeoptimizeDirectMethod)611 TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
612   ScopedObjectAccess soa(Thread::Current());
613   jobject class_loader = LoadDex("Instrumentation");
614   Runtime* const runtime = Runtime::Current();
615   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
616   ClassLinker* class_linker = runtime->GetClassLinker();
617   StackHandleScope<1> hs(soa.Self());
618   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
619   ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
620   ASSERT_TRUE(klass != nullptr);
621   ArtMethod* method_to_deoptimize =
622       klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize);
623   ASSERT_TRUE(method_to_deoptimize != nullptr);
624   ASSERT_TRUE(method_to_deoptimize->IsDirect());
625   ASSERT_TRUE(method_to_deoptimize->GetDeclaringClass() == klass);
626 
627   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
628   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
629 
630   DeoptimizeMethod(soa.Self(), method_to_deoptimize);
631 
632   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
633   EXPECT_TRUE(instr->RunExitHooks());
634   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
635 
636   constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
637   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
638 
639   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
640   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
641 }
642 
TEST_F(InstrumentationTest,FullDeoptimization)643 TEST_F(InstrumentationTest, FullDeoptimization) {
644   ScopedObjectAccess soa(Thread::Current());
645   Runtime* const runtime = Runtime::Current();
646   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
647   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
648 
649   constexpr const char* instrumentation_key = "FullDeoptimization";
650   DeoptimizeEverything(soa.Self(), instrumentation_key);
651 
652   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
653   EXPECT_TRUE(instr->RunExitHooks());
654   EXPECT_TRUE(instr->InterpreterStubsInstalled());
655 
656   UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
657 
658   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
659 }
660 
TEST_F(InstrumentationTest,MixedDeoptimization)661 TEST_F(InstrumentationTest, MixedDeoptimization) {
662   ScopedObjectAccess soa(Thread::Current());
663   jobject class_loader = LoadDex("Instrumentation");
664   Runtime* const runtime = Runtime::Current();
665   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
666   ClassLinker* class_linker = runtime->GetClassLinker();
667   StackHandleScope<1> hs(soa.Self());
668   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
669   ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
670   ASSERT_TRUE(klass != nullptr);
671   ArtMethod* method_to_deoptimize =
672       klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize);
673   ASSERT_TRUE(method_to_deoptimize != nullptr);
674   ASSERT_TRUE(method_to_deoptimize->IsDirect());
675   ASSERT_TRUE(method_to_deoptimize->GetDeclaringClass() == klass);
676 
677   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
678   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
679 
680   DeoptimizeMethod(soa.Self(), method_to_deoptimize);
681   // Deoptimizing a method does not change instrumentation level.
682   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
683             GetCurrentInstrumentationLevel());
684   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
685   EXPECT_TRUE(instr->RunExitHooks());
686   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
687 
688   constexpr const char* instrumentation_key = "MixedDeoptimization";
689   DeoptimizeEverything(soa.Self(), instrumentation_key);
690   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
691             GetCurrentInstrumentationLevel());
692   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
693   EXPECT_TRUE(instr->RunExitHooks());
694   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
695 
696   UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
697   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
698             GetCurrentInstrumentationLevel());
699   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
700   EXPECT_TRUE(instr->RunExitHooks());
701   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
702 
703   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
704   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
705             GetCurrentInstrumentationLevel());
706   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
707   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
708 }
709 
TEST_F(InstrumentationTest,MethodTracing_Interpreter)710 TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
711   ScopedObjectAccess soa(Thread::Current());
712   Runtime* const runtime = Runtime::Current();
713   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
714   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
715 
716   constexpr const char* instrumentation_key = "MethodTracing";
717   EnableMethodTracing(soa.Self(), instrumentation_key, true);
718   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
719             GetCurrentInstrumentationLevel());
720   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
721   EXPECT_TRUE(instr->RunExitHooks());
722 
723   DisableMethodTracing(soa.Self(), instrumentation_key);
724   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
725             GetCurrentInstrumentationLevel());
726   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
727 }
728 
TEST_F(InstrumentationTest,MethodTracing_InstrumentationEntryExitStubs)729 TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
730   ScopedObjectAccess soa(Thread::Current());
731   Runtime* const runtime = Runtime::Current();
732   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
733   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
734 
735   constexpr const char* instrumentation_key = "MethodTracing";
736   EnableMethodTracing(soa.Self(), instrumentation_key, false);
737   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks,
738             GetCurrentInstrumentationLevel());
739   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
740   EXPECT_TRUE(instr->RunExitHooks());
741 
742   DisableMethodTracing(soa.Self(), instrumentation_key);
743   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
744             GetCurrentInstrumentationLevel());
745   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
746 }
747 
748 // We use a macro to print the line number where the test is failing.
749 #define CHECK_INSTRUMENTATION(_level, _user_count)                                      \
750   do {                                                                                  \
751     Instrumentation* const instr = Runtime::Current()->GetInstrumentation();            \
752     bool interpreter =                                                                  \
753       ((_level) == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);  \
754     EXPECT_EQ(_level, GetCurrentInstrumentationLevel());                                \
755     EXPECT_EQ(_user_count, GetInstrumentationUserCount());                              \
756     if (instr->IsForcedInterpretOnly()) {                                               \
757       EXPECT_TRUE(instr->InterpretOnly());                                              \
758     } else if (interpreter) {                                                           \
759       EXPECT_TRUE(instr->InterpretOnly());                                              \
760     } else {                                                                            \
761       EXPECT_FALSE(instr->InterpretOnly());                                             \
762     }                                                                                   \
763     if (interpreter) {                                                                  \
764       EXPECT_TRUE(instr->AreAllMethodsDeoptimized());                                   \
765     } else {                                                                            \
766       EXPECT_FALSE(instr->AreAllMethodsDeoptimized());                                  \
767     }                                                                                   \
768   } while (false)
769 
TEST_F(InstrumentationTest,ConfigureStubs_Nothing)770 TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
771   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
772 
773   // Check no-op.
774   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
775   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
776 }
777 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubs)778 TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
779   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
780 
781   // Check we can switch to instrumentation stubs
782   CheckConfigureStubs(kClientOneKey,
783                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
784   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
785 
786   // Check we can disable instrumentation.
787   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
788   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
789 }
790 
TEST_F(InstrumentationTest,ConfigureStubs_Interpreter)791 TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
792   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
793 
794   // Check we can switch to interpreter
795   CheckConfigureStubs(kClientOneKey,
796                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
797   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
798 
799   // Check we can disable instrumentation.
800   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
801   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
802 }
803 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreter)804 TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
805   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
806 
807   // Configure stubs with instrumentation stubs.
808   CheckConfigureStubs(kClientOneKey,
809                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
810   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
811 
812   // Configure stubs with interpreter.
813   CheckConfigureStubs(kClientOneKey,
814                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
815   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
816 
817   // Check we can disable instrumentation.
818   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
819   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
820 }
821 
TEST_F(InstrumentationTest,ConfigureStubs_InterpreterToInstrumentationStubs)822 TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
823   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
824 
825   // Configure stubs with interpreter.
826   CheckConfigureStubs(kClientOneKey,
827                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
828   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
829 
830   // Configure stubs with instrumentation stubs.
831   CheckConfigureStubs(kClientOneKey,
832                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
833   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
834 
835   // Check we can disable instrumentation.
836   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
837   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
838 }
839 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs)840 TEST_F(InstrumentationTest,
841        ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
842   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
843 
844   // Configure stubs with instrumentation stubs.
845   CheckConfigureStubs(kClientOneKey,
846                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
847   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
848 
849   // Configure stubs with interpreter.
850   CheckConfigureStubs(kClientOneKey,
851                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
852   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
853 
854   // Configure stubs with instrumentation stubs again.
855   CheckConfigureStubs(kClientOneKey,
856                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
857   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
858 
859   // Check we can disable instrumentation.
860   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
861   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
862 }
863 
TEST_F(InstrumentationTest,MultiConfigureStubs_Nothing)864 TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
865   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
866 
867   // Check kInstrumentNothing with two clients.
868   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
869   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
870 
871   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
872   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
873 }
874 
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubs)875 TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
876   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
877 
878   // Configure stubs with instrumentation stubs for 1st client.
879   CheckConfigureStubs(kClientOneKey,
880                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
881   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
882 
883   // Configure stubs with instrumentation stubs for 2nd client.
884   CheckConfigureStubs(kClientTwoKey,
885                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
886   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 2U);
887 
888   // 1st client requests instrumentation deactivation but 2nd client still needs
889   // instrumentation stubs.
890   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
891   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
892 
893   // 2nd client requests instrumentation deactivation
894   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
895   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
896 }
897 
TEST_F(InstrumentationTest,MultiConfigureStubs_Interpreter)898 TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
899   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
900 
901   // Configure stubs with interpreter for 1st client.
902   CheckConfigureStubs(kClientOneKey,
903                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
904   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
905 
906   // Configure stubs with interpreter for 2nd client.
907   CheckConfigureStubs(kClientTwoKey,
908                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
909   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
910 
911   // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
912   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
913   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
914 
915   // 2nd client requests instrumentation deactivation
916   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
917   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
918 }
919 
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubsThenInterpreter)920 TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
921   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
922 
923   // Configure stubs with instrumentation stubs for 1st client.
924   CheckConfigureStubs(kClientOneKey,
925                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
926   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
927 
928   // Configure stubs with interpreter for 2nd client.
929   CheckConfigureStubs(kClientTwoKey,
930                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
931   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
932 
933   // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
934   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
935   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
936 
937   // 2nd client requests instrumentation deactivation
938   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
939   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
940 }
941 
TEST_F(InstrumentationTest,MultiConfigureStubs_InterpreterThenInstrumentationStubs)942 TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
943   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
944 
945   // Configure stubs with interpreter for 1st client.
946   CheckConfigureStubs(kClientOneKey,
947                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
948   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
949 
950   // Configure stubs with instrumentation stubs for 2nd client.
951   CheckConfigureStubs(kClientTwoKey,
952                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
953   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
954 
955   // 1st client requests instrumentation deactivation but 2nd client still needs
956   // instrumentation stubs.
957   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
958   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
959 
960   // 2nd client requests instrumentation deactivation
961   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
962   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
963 }
964 
965 }  // namespace instrumentation
966 }  // namespace art
967