instrumentation_test.cc revision e401d146407d61eeb99f8d6176b2ac13c4df1e33
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
30namespace art {
31namespace instrumentation {
32
33class TestInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
34 public:
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
41  virtual ~TestInstrumentationListener() {}
42
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
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
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
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
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
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
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
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
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
132class 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
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
151  Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
152    return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
153  }
154
155  size_t GetInstrumentationUserCount() {
156    ScopedObjectAccess soa(Thread::Current());
157    return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
158  }
159
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
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
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
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
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
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
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:
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
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
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
374TEST_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.
398TEST_F(InstrumentationTest, MethodEntryEvent) {
399  TestEvent(instrumentation::Instrumentation::kMethodEntered);
400}
401
402TEST_F(InstrumentationTest, MethodExitEvent) {
403  TestEvent(instrumentation::Instrumentation::kMethodExited);
404}
405
406TEST_F(InstrumentationTest, MethodUnwindEvent) {
407  TestEvent(instrumentation::Instrumentation::kMethodUnwind);
408}
409
410TEST_F(InstrumentationTest, DexPcMovedEvent) {
411  TestEvent(instrumentation::Instrumentation::kDexPcMoved);
412}
413
414TEST_F(InstrumentationTest, FieldReadEvent) {
415  TestEvent(instrumentation::Instrumentation::kFieldRead);
416}
417
418TEST_F(InstrumentationTest, FieldWriteEvent) {
419  TestEvent(instrumentation::Instrumentation::kFieldWritten);
420}
421
422TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
423  TestEvent(instrumentation::Instrumentation::kExceptionCaught);
424}
425
426TEST_F(InstrumentationTest, BackwardBranchEvent) {
427  TestEvent(instrumentation::Instrumentation::kBackwardBranch);
428}
429
430TEST_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
460TEST_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
477TEST_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
524TEST_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
543TEST_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
584TEST_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
592TEST_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
606TEST_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
619TEST_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
638TEST_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
657TEST_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
683TEST_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
694TEST_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
720TEST_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
742TEST_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
765TEST_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