OSDN Git Service

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