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