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