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 "common_runtime_test.h"
20 #include "common_throws.h"
21 #include "class_linker-inl.h"
22 #include "dex_file.h"
23 #include "handle_scope-inl.h"
24 #include "jvalue.h"
25 #include "runtime.h"
26 #include "scoped_thread_state_change.h"
27 #include "thread_list.h"
28 #include "thread-inl.h"
29 
30 namespace art {
31 namespace instrumentation {
32 
33 class TestInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
34  public:
TestInstrumentationListener()35   TestInstrumentationListener()
36     : received_method_enter_event(false), received_method_exit_event(false),
37       received_method_unwind_event(false), received_dex_pc_moved_event(false),
38       received_field_read_event(false), received_field_written_event(false),
39       received_exception_caught_event(false), received_backward_branch_event(false) {}
40 
~TestInstrumentationListener()41   virtual ~TestInstrumentationListener() {}
42 
MethodEntered(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED)43   void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
44                      mirror::Object* this_object ATTRIBUTE_UNUSED,
45                      ArtMethod* method ATTRIBUTE_UNUSED,
46                      uint32_t dex_pc ATTRIBUTE_UNUSED)
47       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
48     received_method_enter_event = true;
49   }
50 
MethodExited(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,const JValue & return_value ATTRIBUTE_UNUSED)51   void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
52                     mirror::Object* this_object ATTRIBUTE_UNUSED,
53                     ArtMethod* method ATTRIBUTE_UNUSED,
54                     uint32_t dex_pc ATTRIBUTE_UNUSED,
55                     const JValue& return_value ATTRIBUTE_UNUSED)
56       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
57     received_method_exit_event = true;
58   }
59 
MethodUnwind(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED)60   void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
61                     mirror::Object* this_object ATTRIBUTE_UNUSED,
62                     ArtMethod* method ATTRIBUTE_UNUSED,
63                     uint32_t dex_pc ATTRIBUTE_UNUSED)
64       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
65     received_method_unwind_event = true;
66   }
67 
DexPcMoved(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t new_dex_pc ATTRIBUTE_UNUSED)68   void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
69                   mirror::Object* this_object ATTRIBUTE_UNUSED,
70                   ArtMethod* method ATTRIBUTE_UNUSED,
71                   uint32_t new_dex_pc ATTRIBUTE_UNUSED)
72       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
73     received_dex_pc_moved_event = true;
74   }
75 
FieldRead(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,ArtField * field ATTRIBUTE_UNUSED)76   void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
77                  mirror::Object* this_object ATTRIBUTE_UNUSED,
78                  ArtMethod* method ATTRIBUTE_UNUSED,
79                  uint32_t dex_pc ATTRIBUTE_UNUSED,
80                  ArtField* field ATTRIBUTE_UNUSED)
81       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
82     received_field_read_event = true;
83   }
84 
FieldWritten(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,ArtField * field ATTRIBUTE_UNUSED,const JValue & field_value ATTRIBUTE_UNUSED)85   void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
86                     mirror::Object* this_object ATTRIBUTE_UNUSED,
87                     ArtMethod* method ATTRIBUTE_UNUSED,
88                     uint32_t dex_pc ATTRIBUTE_UNUSED,
89                     ArtField* field ATTRIBUTE_UNUSED,
90                     const JValue& field_value ATTRIBUTE_UNUSED)
91       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
92     received_field_written_event = true;
93   }
94 
ExceptionCaught(Thread * thread ATTRIBUTE_UNUSED,mirror::Throwable * exception_object ATTRIBUTE_UNUSED)95   void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
96                        mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
97       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
98     received_exception_caught_event = true;
99   }
100 
BackwardBranch(Thread * thread ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,int32_t dex_pc_offset ATTRIBUTE_UNUSED)101   void BackwardBranch(Thread* thread ATTRIBUTE_UNUSED,
102                       ArtMethod* method ATTRIBUTE_UNUSED,
103                       int32_t dex_pc_offset ATTRIBUTE_UNUSED)
104       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
105     received_backward_branch_event = true;
106   }
107 
Reset()108   void Reset() {
109     received_method_enter_event = false;
110     received_method_exit_event = false;
111     received_method_unwind_event = false;
112     received_dex_pc_moved_event = false;
113     received_field_read_event = false;
114     received_field_written_event = false;
115     received_exception_caught_event = false;
116     received_backward_branch_event = false;
117   }
118 
119   bool received_method_enter_event;
120   bool received_method_exit_event;
121   bool received_method_unwind_event;
122   bool received_dex_pc_moved_event;
123   bool received_field_read_event;
124   bool received_field_written_event;
125   bool received_exception_caught_event;
126   bool received_backward_branch_event;
127 
128  private:
129   DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
130 };
131 
132 class InstrumentationTest : public CommonRuntimeTest {
133  public:
134   // Unique keys used to test Instrumentation::ConfigureStubs.
135   static constexpr const char* kClientOneKey = "TestClient1";
136   static constexpr const char* kClientTwoKey = "TestClient2";
137 
CheckConfigureStubs(const char * key,Instrumentation::InstrumentationLevel level)138   void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
139     ScopedObjectAccess soa(Thread::Current());
140     instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
141     {
142       soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
143       Runtime* runtime = Runtime::Current();
144       runtime->GetThreadList()->SuspendAll("Instrumentation::ConfigureStubs");
145       instr->ConfigureStubs(key, level);
146       runtime->GetThreadList()->ResumeAll();
147       soa.Self()->TransitionFromSuspendedToRunnable();
148     }
149   }
150 
GetCurrentInstrumentationLevel()151   Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
152     return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
153   }
154 
GetInstrumentationUserCount()155   size_t GetInstrumentationUserCount() {
156     ScopedObjectAccess soa(Thread::Current());
157     return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
158   }
159 
TestEvent(uint32_t instrumentation_event)160   void TestEvent(uint32_t instrumentation_event) {
161     ScopedObjectAccess soa(Thread::Current());
162     instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
163     TestInstrumentationListener listener;
164     {
165       soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
166       Runtime* runtime = Runtime::Current();
167       runtime->GetThreadList()->SuspendAll("Add instrumentation listener");
168       instr->AddListener(&listener, instrumentation_event);
169       runtime->GetThreadList()->ResumeAll();
170       soa.Self()->TransitionFromSuspendedToRunnable();
171     }
172 
173     ArtMethod* const event_method = nullptr;
174     mirror::Object* const event_obj = nullptr;
175     const uint32_t event_dex_pc = 0;
176 
177     // Check the listener is registered and is notified of the event.
178     EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
179     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
180     ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
181     EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
182 
183     listener.Reset();
184     {
185       soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
186       Runtime* runtime = Runtime::Current();
187       runtime->GetThreadList()->SuspendAll("Remove instrumentation listener");
188       instr->RemoveListener(&listener, instrumentation_event);
189       runtime->GetThreadList()->ResumeAll();
190       soa.Self()->TransitionFromSuspendedToRunnable();
191     }
192 
193     // Check the listener is not registered and is not notified of the event.
194     EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
195     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
196     ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
197     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
198   }
199 
DeoptimizeMethod(Thread * self,ArtMethod * method,bool enable_deoptimization)200   void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
201       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
202     Runtime* runtime = Runtime::Current();
203     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
204     self->TransitionFromRunnableToSuspended(kSuspended);
205     runtime->GetThreadList()->SuspendAll("Single method deoptimization");
206     if (enable_deoptimization) {
207       instrumentation->EnableDeoptimization();
208     }
209     instrumentation->Deoptimize(method);
210     runtime->GetThreadList()->ResumeAll();
211     self->TransitionFromSuspendedToRunnable();
212   }
213 
UndeoptimizeMethod(Thread * self,ArtMethod * method,const char * key,bool disable_deoptimization)214   void UndeoptimizeMethod(Thread* self, ArtMethod* method,
215                           const char* key, bool disable_deoptimization)
216       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
217     Runtime* runtime = Runtime::Current();
218     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
219     self->TransitionFromRunnableToSuspended(kSuspended);
220     runtime->GetThreadList()->SuspendAll("Single method undeoptimization");
221     instrumentation->Undeoptimize(method);
222     if (disable_deoptimization) {
223       instrumentation->DisableDeoptimization(key);
224     }
225     runtime->GetThreadList()->ResumeAll();
226     self->TransitionFromSuspendedToRunnable();
227   }
228 
DeoptimizeEverything(Thread * self,const char * key,bool enable_deoptimization)229   void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
230         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
231     Runtime* runtime = Runtime::Current();
232     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
233     self->TransitionFromRunnableToSuspended(kSuspended);
234     runtime->GetThreadList()->SuspendAll("Full deoptimization");
235     if (enable_deoptimization) {
236       instrumentation->EnableDeoptimization();
237     }
238     instrumentation->DeoptimizeEverything(key);
239     runtime->GetThreadList()->ResumeAll();
240     self->TransitionFromSuspendedToRunnable();
241   }
242 
UndeoptimizeEverything(Thread * self,const char * key,bool disable_deoptimization)243   void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
244         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
245     Runtime* runtime = Runtime::Current();
246     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
247     self->TransitionFromRunnableToSuspended(kSuspended);
248     runtime->GetThreadList()->SuspendAll("Full undeoptimization");
249     instrumentation->UndeoptimizeEverything(key);
250     if (disable_deoptimization) {
251       instrumentation->DisableDeoptimization(key);
252     }
253     runtime->GetThreadList()->ResumeAll();
254     self->TransitionFromSuspendedToRunnable();
255   }
256 
EnableMethodTracing(Thread * self,const char * key,bool needs_interpreter)257   void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
258         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
259     Runtime* runtime = Runtime::Current();
260     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
261     self->TransitionFromRunnableToSuspended(kSuspended);
262     runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
263     instrumentation->EnableMethodTracing(key, needs_interpreter);
264     runtime->GetThreadList()->ResumeAll();
265     self->TransitionFromSuspendedToRunnable();
266   }
267 
DisableMethodTracing(Thread * self,const char * key)268   void DisableMethodTracing(Thread* self, const char* key)
269         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
270     Runtime* runtime = Runtime::Current();
271     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
272     self->TransitionFromRunnableToSuspended(kSuspended);
273     runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
274     instrumentation->DisableMethodTracing(key);
275     runtime->GetThreadList()->ResumeAll();
276     self->TransitionFromSuspendedToRunnable();
277   }
278 
279  private:
HasEventListener(const instrumentation::Instrumentation * instr,uint32_t event_type)280   static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
281       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
282     switch (event_type) {
283       case instrumentation::Instrumentation::kMethodEntered:
284         return instr->HasMethodEntryListeners();
285       case instrumentation::Instrumentation::kMethodExited:
286         return instr->HasMethodExitListeners();
287       case instrumentation::Instrumentation::kMethodUnwind:
288         return instr->HasMethodUnwindListeners();
289       case instrumentation::Instrumentation::kDexPcMoved:
290         return instr->HasDexPcListeners();
291       case instrumentation::Instrumentation::kFieldRead:
292         return instr->HasFieldReadListeners();
293       case instrumentation::Instrumentation::kFieldWritten:
294         return instr->HasFieldWriteListeners();
295       case instrumentation::Instrumentation::kExceptionCaught:
296         return instr->HasExceptionCaughtListeners();
297       case instrumentation::Instrumentation::kBackwardBranch:
298         return instr->HasBackwardBranchListeners();
299       default:
300         LOG(FATAL) << "Unknown instrumentation event " << event_type;
301         UNREACHABLE();
302     }
303   }
304 
ReportEvent(const instrumentation::Instrumentation * instr,uint32_t event_type,Thread * self,ArtMethod * method,mirror::Object * obj,uint32_t dex_pc)305   static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
306                           Thread* self, ArtMethod* method, mirror::Object* obj,
307                           uint32_t dex_pc)
308       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
309     switch (event_type) {
310       case instrumentation::Instrumentation::kMethodEntered:
311         instr->MethodEnterEvent(self, obj, method, dex_pc);
312         break;
313       case instrumentation::Instrumentation::kMethodExited: {
314         JValue value;
315         instr->MethodExitEvent(self, obj, method, dex_pc, value);
316         break;
317       }
318       case instrumentation::Instrumentation::kMethodUnwind:
319         instr->MethodUnwindEvent(self, obj, method, dex_pc);
320         break;
321       case instrumentation::Instrumentation::kDexPcMoved:
322         instr->DexPcMovedEvent(self, obj, method, dex_pc);
323         break;
324       case instrumentation::Instrumentation::kFieldRead:
325         instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
326         break;
327       case instrumentation::Instrumentation::kFieldWritten: {
328         JValue value;
329         instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
330         break;
331       }
332       case instrumentation::Instrumentation::kExceptionCaught: {
333         ThrowArithmeticExceptionDivideByZero();
334         mirror::Throwable* event_exception = self->GetException();
335         instr->ExceptionCaughtEvent(self, event_exception);
336         self->ClearException();
337         break;
338       }
339       case instrumentation::Instrumentation::kBackwardBranch:
340         instr->BackwardBranch(self, method, dex_pc);
341         break;
342       default:
343         LOG(FATAL) << "Unknown instrumentation event " << event_type;
344         UNREACHABLE();
345     }
346   }
347 
DidListenerReceiveEvent(const TestInstrumentationListener & listener,uint32_t event_type)348   static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
349                                       uint32_t event_type) {
350     switch (event_type) {
351       case instrumentation::Instrumentation::kMethodEntered:
352         return listener.received_method_enter_event;
353       case instrumentation::Instrumentation::kMethodExited:
354         return listener.received_method_exit_event;
355       case instrumentation::Instrumentation::kMethodUnwind:
356         return listener.received_method_unwind_event;
357       case instrumentation::Instrumentation::kDexPcMoved:
358         return listener.received_dex_pc_moved_event;
359       case instrumentation::Instrumentation::kFieldRead:
360         return listener.received_field_read_event;
361       case instrumentation::Instrumentation::kFieldWritten:
362         return listener.received_field_written_event;
363       case instrumentation::Instrumentation::kExceptionCaught:
364         return listener.received_exception_caught_event;
365       case instrumentation::Instrumentation::kBackwardBranch:
366         return listener.received_backward_branch_event;
367       default:
368         LOG(FATAL) << "Unknown instrumentation event " << event_type;
369         UNREACHABLE();
370     }
371   }
372 };
373 
TEST_F(InstrumentationTest,NoInstrumentation)374 TEST_F(InstrumentationTest, NoInstrumentation) {
375   ScopedObjectAccess soa(Thread::Current());
376   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
377   ASSERT_NE(instr, nullptr);
378 
379   EXPECT_FALSE(instr->AreExitStubsInstalled());
380   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
381   EXPECT_FALSE(instr->IsActive());
382   EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
383 
384   // Test interpreter table is the default one.
385   EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
386 
387   // Check there is no registered listener.
388   EXPECT_FALSE(instr->HasDexPcListeners());
389   EXPECT_FALSE(instr->HasExceptionCaughtListeners());
390   EXPECT_FALSE(instr->HasFieldReadListeners());
391   EXPECT_FALSE(instr->HasFieldWriteListeners());
392   EXPECT_FALSE(instr->HasMethodEntryListeners());
393   EXPECT_FALSE(instr->HasMethodExitListeners());
394   EXPECT_FALSE(instr->IsActive());
395 }
396 
397 // Test instrumentation listeners for each event.
TEST_F(InstrumentationTest,MethodEntryEvent)398 TEST_F(InstrumentationTest, MethodEntryEvent) {
399   TestEvent(instrumentation::Instrumentation::kMethodEntered);
400 }
401 
TEST_F(InstrumentationTest,MethodExitEvent)402 TEST_F(InstrumentationTest, MethodExitEvent) {
403   TestEvent(instrumentation::Instrumentation::kMethodExited);
404 }
405 
TEST_F(InstrumentationTest,MethodUnwindEvent)406 TEST_F(InstrumentationTest, MethodUnwindEvent) {
407   TestEvent(instrumentation::Instrumentation::kMethodUnwind);
408 }
409 
TEST_F(InstrumentationTest,DexPcMovedEvent)410 TEST_F(InstrumentationTest, DexPcMovedEvent) {
411   TestEvent(instrumentation::Instrumentation::kDexPcMoved);
412 }
413 
TEST_F(InstrumentationTest,FieldReadEvent)414 TEST_F(InstrumentationTest, FieldReadEvent) {
415   TestEvent(instrumentation::Instrumentation::kFieldRead);
416 }
417 
TEST_F(InstrumentationTest,FieldWriteEvent)418 TEST_F(InstrumentationTest, FieldWriteEvent) {
419   TestEvent(instrumentation::Instrumentation::kFieldWritten);
420 }
421 
TEST_F(InstrumentationTest,ExceptionCaughtEvent)422 TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
423   TestEvent(instrumentation::Instrumentation::kExceptionCaught);
424 }
425 
TEST_F(InstrumentationTest,BackwardBranchEvent)426 TEST_F(InstrumentationTest, BackwardBranchEvent) {
427   TestEvent(instrumentation::Instrumentation::kBackwardBranch);
428 }
429 
TEST_F(InstrumentationTest,DeoptimizeDirectMethod)430 TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
431   ScopedObjectAccess soa(Thread::Current());
432   jobject class_loader = LoadDex("Instrumentation");
433   Runtime* const runtime = Runtime::Current();
434   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
435   ClassLinker* class_linker = runtime->GetClassLinker();
436   StackHandleScope<1> hs(soa.Self());
437   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
438   mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
439   ASSERT_TRUE(klass != nullptr);
440   ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
441                                                                     sizeof(void*));
442   ASSERT_TRUE(method_to_deoptimize != nullptr);
443 
444   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
445   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
446 
447   DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
448 
449   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
450   EXPECT_TRUE(instr->AreExitStubsInstalled());
451   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
452 
453   constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
454   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
455 
456   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
457   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
458 }
459 
TEST_F(InstrumentationTest,FullDeoptimization)460 TEST_F(InstrumentationTest, FullDeoptimization) {
461   ScopedObjectAccess soa(Thread::Current());
462   Runtime* const runtime = Runtime::Current();
463   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
464   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
465 
466   constexpr const char* instrumentation_key = "FullDeoptimization";
467   DeoptimizeEverything(soa.Self(), instrumentation_key, true);
468 
469   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
470   EXPECT_TRUE(instr->AreExitStubsInstalled());
471 
472   UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
473 
474   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
475 }
476 
TEST_F(InstrumentationTest,MixedDeoptimization)477 TEST_F(InstrumentationTest, MixedDeoptimization) {
478   ScopedObjectAccess soa(Thread::Current());
479   jobject class_loader = LoadDex("Instrumentation");
480   Runtime* const runtime = Runtime::Current();
481   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
482   ClassLinker* class_linker = runtime->GetClassLinker();
483   StackHandleScope<1> hs(soa.Self());
484   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
485   mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
486   ASSERT_TRUE(klass != nullptr);
487   ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
488                                                                     sizeof(void*));
489   ASSERT_TRUE(method_to_deoptimize != nullptr);
490 
491   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
492   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
493 
494   DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
495   // Deoptimizing a method does not change instrumentation level.
496   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
497             GetCurrentInstrumentationLevel());
498   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
499   EXPECT_TRUE(instr->AreExitStubsInstalled());
500   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
501 
502   constexpr const char* instrumentation_key = "MixedDeoptimization";
503   DeoptimizeEverything(soa.Self(), instrumentation_key, false);
504   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
505             GetCurrentInstrumentationLevel());
506   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
507   EXPECT_TRUE(instr->AreExitStubsInstalled());
508   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
509 
510   UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
511   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
512             GetCurrentInstrumentationLevel());
513   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
514   EXPECT_TRUE(instr->AreExitStubsInstalled());
515   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
516 
517   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
518   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
519             GetCurrentInstrumentationLevel());
520   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
521   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
522 }
523 
TEST_F(InstrumentationTest,MethodTracing_Interpreter)524 TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
525   ScopedObjectAccess soa(Thread::Current());
526   Runtime* const runtime = Runtime::Current();
527   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
528   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
529 
530   constexpr const char* instrumentation_key = "MethodTracing";
531   EnableMethodTracing(soa.Self(), instrumentation_key, true);
532   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
533             GetCurrentInstrumentationLevel());
534   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
535   EXPECT_TRUE(instr->AreExitStubsInstalled());
536 
537   DisableMethodTracing(soa.Self(), instrumentation_key);
538   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
539             GetCurrentInstrumentationLevel());
540   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
541 }
542 
TEST_F(InstrumentationTest,MethodTracing_InstrumentationEntryExitStubs)543 TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
544   ScopedObjectAccess soa(Thread::Current());
545   Runtime* const runtime = Runtime::Current();
546   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
547   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
548 
549   constexpr const char* instrumentation_key = "MethodTracing";
550   EnableMethodTracing(soa.Self(), instrumentation_key, false);
551   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
552             GetCurrentInstrumentationLevel());
553   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
554   EXPECT_TRUE(instr->AreExitStubsInstalled());
555 
556   DisableMethodTracing(soa.Self(), instrumentation_key);
557   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
558             GetCurrentInstrumentationLevel());
559   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
560 }
561 
562 // We use a macro to print the line number where the test is failing.
563 #define CHECK_INSTRUMENTATION(_level, _user_count)                                      \
564   do {                                                                                  \
565     Instrumentation* const instr = Runtime::Current()->GetInstrumentation();            \
566     bool interpreter =                                                                  \
567       (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);    \
568     EXPECT_EQ(_level, GetCurrentInstrumentationLevel());                                \
569     EXPECT_EQ(_user_count, GetInstrumentationUserCount());                              \
570     if (instr->IsForcedInterpretOnly()) {                                               \
571       EXPECT_TRUE(instr->InterpretOnly());                                              \
572     } else if (interpreter) {                                                           \
573       EXPECT_TRUE(instr->InterpretOnly());                                              \
574     } else {                                                                            \
575       EXPECT_FALSE(instr->InterpretOnly());                                             \
576     }                                                                                   \
577     if (interpreter) {                                                                  \
578       EXPECT_TRUE(instr->AreAllMethodsDeoptimized());                                   \
579     } else {                                                                            \
580       EXPECT_FALSE(instr->AreAllMethodsDeoptimized());                                  \
581     }                                                                                   \
582   } while (false)
583 
TEST_F(InstrumentationTest,ConfigureStubs_Nothing)584 TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
585   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
586 
587   // Check no-op.
588   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
589   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
590 }
591 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubs)592 TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
593   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
594 
595   // Check we can switch to instrumentation stubs
596   CheckConfigureStubs(kClientOneKey,
597                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
598   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
599                         1U);
600 
601   // Check we can disable instrumentation.
602   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
603   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
604 }
605 
TEST_F(InstrumentationTest,ConfigureStubs_Interpreter)606 TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
607   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
608 
609   // Check we can switch to interpreter
610   CheckConfigureStubs(kClientOneKey,
611                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
612   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
613 
614   // Check we can disable instrumentation.
615   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
616   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
617 }
618 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreter)619 TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
620   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
621 
622   // Configure stubs with instrumentation stubs.
623   CheckConfigureStubs(kClientOneKey,
624                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
625   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
626                         1U);
627 
628   // Configure stubs with interpreter.
629   CheckConfigureStubs(kClientOneKey,
630                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
631   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
632 
633   // Check we can disable instrumentation.
634   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
635   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
636 }
637 
TEST_F(InstrumentationTest,ConfigureStubs_InterpreterToInstrumentationStubs)638 TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
639   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
640 
641   // Configure stubs with interpreter.
642   CheckConfigureStubs(kClientOneKey,
643                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
644   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
645 
646   // Configure stubs with instrumentation stubs.
647   CheckConfigureStubs(kClientOneKey,
648                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
649   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
650                         1U);
651 
652   // Check we can disable instrumentation.
653   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
654   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
655 }
656 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs)657 TEST_F(InstrumentationTest,
658        ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
659   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
660 
661   // Configure stubs with instrumentation stubs.
662   CheckConfigureStubs(kClientOneKey,
663                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
664   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
665                         1U);
666 
667   // Configure stubs with interpreter.
668   CheckConfigureStubs(kClientOneKey,
669                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
670   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
671 
672   // Configure stubs with instrumentation stubs again.
673   CheckConfigureStubs(kClientOneKey,
674                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
675   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
676                         1U);
677 
678   // Check we can disable instrumentation.
679   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
680   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
681 }
682 
TEST_F(InstrumentationTest,MultiConfigureStubs_Nothing)683 TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
684   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
685 
686   // Check kInstrumentNothing with two clients.
687   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
688   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
689 
690   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
691   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
692 }
693 
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubs)694 TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
695   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
696 
697   // Configure stubs with instrumentation stubs for 1st client.
698   CheckConfigureStubs(kClientOneKey,
699                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
700   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
701                         1U);
702 
703   // Configure stubs with instrumentation stubs for 2nd client.
704   CheckConfigureStubs(kClientTwoKey,
705                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
706   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
707                         2U);
708 
709   // 1st client requests instrumentation deactivation but 2nd client still needs
710   // instrumentation stubs.
711   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
712   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
713                         1U);
714 
715   // 2nd client requests instrumentation deactivation
716   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
717   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
718 }
719 
TEST_F(InstrumentationTest,MultiConfigureStubs_Interpreter)720 TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
721   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
722 
723   // Configure stubs with interpreter for 1st client.
724   CheckConfigureStubs(kClientOneKey,
725                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
726   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
727 
728   // Configure stubs with interpreter for 2nd client.
729   CheckConfigureStubs(kClientTwoKey,
730                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
731   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
732 
733   // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
734   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
735   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
736 
737   // 2nd client requests instrumentation deactivation
738   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
739   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
740 }
741 
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubsThenInterpreter)742 TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
743   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
744 
745   // Configure stubs with instrumentation stubs for 1st client.
746   CheckConfigureStubs(kClientOneKey,
747                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
748   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
749                         1U);
750 
751   // Configure stubs with interpreter for 2nd client.
752   CheckConfigureStubs(kClientTwoKey,
753                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
754   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
755 
756   // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
757   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
758   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
759 
760   // 2nd client requests instrumentation deactivation
761   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
762   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
763 }
764 
TEST_F(InstrumentationTest,MultiConfigureStubs_InterpreterThenInstrumentationStubs)765 TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
766   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
767 
768   // Configure stubs with interpreter for 1st client.
769   CheckConfigureStubs(kClientOneKey,
770                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
771   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
772 
773   // Configure stubs with instrumentation stubs for 2nd client.
774   CheckConfigureStubs(kClientTwoKey,
775                       Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
776   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
777 
778   // 1st client requests instrumentation deactivation but 2nd client still needs
779   // instrumentation stubs.
780   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
781   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
782                         1U);
783 
784   // 2nd client requests instrumentation deactivation
785   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
786   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
787 }
788 
789 }  // namespace instrumentation
790 }  // namespace art
791