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