instrumentation_test.cc revision 798eab03120f6189e8f6aa804d67af1b1d9f00b0
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_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 36namespace art { 37namespace instrumentation { 38 39class 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 197class 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 491TEST_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. 516TEST_F(InstrumentationTest, MethodEntryEvent) { 517 TestEvent(instrumentation::Instrumentation::kMethodEntered); 518} 519 520TEST_F(InstrumentationTest, MethodExitObjectEvent) { 521 ScopedObjectAccess soa(Thread::Current()); 522 jobject class_loader = LoadDex("Instrumentation"); 523 Runtime* const runtime = Runtime::Current(); 524 ClassLinker* class_linker = runtime->GetClassLinker(); 525 StackHandleScope<1> hs(soa.Self()); 526 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 527 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); 528 ASSERT_TRUE(klass != nullptr); 529 ArtMethod* method = 530 klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize); 531 ASSERT_TRUE(method != nullptr); 532 ASSERT_TRUE(method->IsDirect()); 533 ASSERT_TRUE(method->GetDeclaringClass() == klass); 534 TestEvent(instrumentation::Instrumentation::kMethodExited, 535 /*event_method*/ method, 536 /*event_field*/ nullptr, 537 /*with_object*/ true); 538} 539 540TEST_F(InstrumentationTest, MethodExitPrimEvent) { 541 ScopedObjectAccess soa(Thread::Current()); 542 jobject class_loader = LoadDex("Instrumentation"); 543 Runtime* const runtime = Runtime::Current(); 544 ClassLinker* class_linker = runtime->GetClassLinker(); 545 StackHandleScope<1> hs(soa.Self()); 546 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 547 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); 548 ASSERT_TRUE(klass != nullptr); 549 ArtMethod* method = klass->FindClassMethod("returnPrimitive", "()I", kRuntimePointerSize); 550 ASSERT_TRUE(method != nullptr); 551 ASSERT_TRUE(method->IsDirect()); 552 ASSERT_TRUE(method->GetDeclaringClass() == klass); 553 TestEvent(instrumentation::Instrumentation::kMethodExited, 554 /*event_method*/ method, 555 /*event_field*/ nullptr, 556 /*with_object*/ false); 557} 558 559TEST_F(InstrumentationTest, MethodUnwindEvent) { 560 TestEvent(instrumentation::Instrumentation::kMethodUnwind); 561} 562 563TEST_F(InstrumentationTest, DexPcMovedEvent) { 564 TestEvent(instrumentation::Instrumentation::kDexPcMoved); 565} 566 567TEST_F(InstrumentationTest, FieldReadEvent) { 568 TestEvent(instrumentation::Instrumentation::kFieldRead); 569} 570 571TEST_F(InstrumentationTest, WatchedFramePop) { 572 TestEvent(instrumentation::Instrumentation::kWatchedFramePop); 573} 574 575TEST_F(InstrumentationTest, FieldWriteObjectEvent) { 576 ScopedObjectAccess soa(Thread::Current()); 577 jobject class_loader = LoadDex("Instrumentation"); 578 Runtime* const runtime = Runtime::Current(); 579 ClassLinker* class_linker = runtime->GetClassLinker(); 580 StackHandleScope<1> hs(soa.Self()); 581 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 582 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); 583 ASSERT_TRUE(klass != nullptr); 584 ArtField* field = klass->FindDeclaredStaticField("referenceField", "Ljava/lang/Object;"); 585 ASSERT_TRUE(field != nullptr); 586 587 TestEvent(instrumentation::Instrumentation::kFieldWritten, 588 /*event_method*/ nullptr, 589 /*event_field*/ field, 590 /*with_object*/ true); 591} 592 593TEST_F(InstrumentationTest, FieldWritePrimEvent) { 594 ScopedObjectAccess soa(Thread::Current()); 595 jobject class_loader = LoadDex("Instrumentation"); 596 Runtime* const runtime = Runtime::Current(); 597 ClassLinker* class_linker = runtime->GetClassLinker(); 598 StackHandleScope<1> hs(soa.Self()); 599 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 600 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); 601 ASSERT_TRUE(klass != nullptr); 602 ArtField* field = klass->FindDeclaredStaticField("primitiveField", "I"); 603 ASSERT_TRUE(field != nullptr); 604 605 TestEvent(instrumentation::Instrumentation::kFieldWritten, 606 /*event_method*/ nullptr, 607 /*event_field*/ field, 608 /*with_object*/ false); 609} 610 611TEST_F(InstrumentationTest, ExceptionHandledEvent) { 612 TestEvent(instrumentation::Instrumentation::kExceptionHandled); 613} 614 615TEST_F(InstrumentationTest, ExceptionThrownEvent) { 616 TestEvent(instrumentation::Instrumentation::kExceptionThrown); 617} 618 619TEST_F(InstrumentationTest, BranchEvent) { 620 TestEvent(instrumentation::Instrumentation::kBranch); 621} 622 623TEST_F(InstrumentationTest, InvokeVirtualOrInterfaceEvent) { 624 TestEvent(instrumentation::Instrumentation::kInvokeVirtualOrInterface); 625} 626 627TEST_F(InstrumentationTest, DeoptimizeDirectMethod) { 628 ScopedObjectAccess soa(Thread::Current()); 629 jobject class_loader = LoadDex("Instrumentation"); 630 Runtime* const runtime = Runtime::Current(); 631 instrumentation::Instrumentation* instr = runtime->GetInstrumentation(); 632 ClassLinker* class_linker = runtime->GetClassLinker(); 633 StackHandleScope<1> hs(soa.Self()); 634 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 635 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); 636 ASSERT_TRUE(klass != nullptr); 637 ArtMethod* method_to_deoptimize = 638 klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize); 639 ASSERT_TRUE(method_to_deoptimize != nullptr); 640 ASSERT_TRUE(method_to_deoptimize->IsDirect()); 641 ASSERT_TRUE(method_to_deoptimize->GetDeclaringClass() == klass); 642 643 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 644 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize)); 645 646 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true); 647 648 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 649 EXPECT_TRUE(instr->AreExitStubsInstalled()); 650 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize)); 651 652 constexpr const char* instrumentation_key = "DeoptimizeDirectMethod"; 653 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true); 654 655 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 656 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize)); 657} 658 659TEST_F(InstrumentationTest, FullDeoptimization) { 660 ScopedObjectAccess soa(Thread::Current()); 661 Runtime* const runtime = Runtime::Current(); 662 instrumentation::Instrumentation* instr = runtime->GetInstrumentation(); 663 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 664 665 constexpr const char* instrumentation_key = "FullDeoptimization"; 666 DeoptimizeEverything(soa.Self(), instrumentation_key, true); 667 668 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); 669 EXPECT_TRUE(instr->AreExitStubsInstalled()); 670 671 UndeoptimizeEverything(soa.Self(), instrumentation_key, true); 672 673 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 674} 675 676TEST_F(InstrumentationTest, MixedDeoptimization) { 677 ScopedObjectAccess soa(Thread::Current()); 678 jobject class_loader = LoadDex("Instrumentation"); 679 Runtime* const runtime = Runtime::Current(); 680 instrumentation::Instrumentation* instr = runtime->GetInstrumentation(); 681 ClassLinker* class_linker = runtime->GetClassLinker(); 682 StackHandleScope<1> hs(soa.Self()); 683 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 684 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader); 685 ASSERT_TRUE(klass != nullptr); 686 ArtMethod* method_to_deoptimize = 687 klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize); 688 ASSERT_TRUE(method_to_deoptimize != nullptr); 689 ASSERT_TRUE(method_to_deoptimize->IsDirect()); 690 ASSERT_TRUE(method_to_deoptimize->GetDeclaringClass() == klass); 691 692 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 693 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize)); 694 695 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true); 696 // Deoptimizing a method does not change instrumentation level. 697 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing, 698 GetCurrentInstrumentationLevel()); 699 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 700 EXPECT_TRUE(instr->AreExitStubsInstalled()); 701 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize)); 702 703 constexpr const char* instrumentation_key = "MixedDeoptimization"; 704 DeoptimizeEverything(soa.Self(), instrumentation_key, false); 705 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 706 GetCurrentInstrumentationLevel()); 707 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); 708 EXPECT_TRUE(instr->AreExitStubsInstalled()); 709 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize)); 710 711 UndeoptimizeEverything(soa.Self(), instrumentation_key, false); 712 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing, 713 GetCurrentInstrumentationLevel()); 714 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 715 EXPECT_TRUE(instr->AreExitStubsInstalled()); 716 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize)); 717 718 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true); 719 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing, 720 GetCurrentInstrumentationLevel()); 721 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 722 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize)); 723} 724 725TEST_F(InstrumentationTest, MethodTracing_Interpreter) { 726 ScopedObjectAccess soa(Thread::Current()); 727 Runtime* const runtime = Runtime::Current(); 728 instrumentation::Instrumentation* instr = runtime->GetInstrumentation(); 729 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 730 731 constexpr const char* instrumentation_key = "MethodTracing"; 732 EnableMethodTracing(soa.Self(), instrumentation_key, true); 733 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 734 GetCurrentInstrumentationLevel()); 735 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); 736 EXPECT_TRUE(instr->AreExitStubsInstalled()); 737 738 DisableMethodTracing(soa.Self(), instrumentation_key); 739 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing, 740 GetCurrentInstrumentationLevel()); 741 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 742} 743 744TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) { 745 ScopedObjectAccess soa(Thread::Current()); 746 Runtime* const runtime = Runtime::Current(); 747 instrumentation::Instrumentation* instr = runtime->GetInstrumentation(); 748 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 749 750 constexpr const char* instrumentation_key = "MethodTracing"; 751 EnableMethodTracing(soa.Self(), instrumentation_key, false); 752 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 753 GetCurrentInstrumentationLevel()); 754 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 755 EXPECT_TRUE(instr->AreExitStubsInstalled()); 756 757 DisableMethodTracing(soa.Self(), instrumentation_key); 758 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing, 759 GetCurrentInstrumentationLevel()); 760 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); 761} 762 763// We use a macro to print the line number where the test is failing. 764#define CHECK_INSTRUMENTATION(_level, _user_count) \ 765 do { \ 766 Instrumentation* const instr = Runtime::Current()->GetInstrumentation(); \ 767 bool interpreter = \ 768 ((_level) == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); \ 769 EXPECT_EQ(_level, GetCurrentInstrumentationLevel()); \ 770 EXPECT_EQ(_user_count, GetInstrumentationUserCount()); \ 771 if (instr->IsForcedInterpretOnly()) { \ 772 EXPECT_TRUE(instr->InterpretOnly()); \ 773 } else if (interpreter) { \ 774 EXPECT_TRUE(instr->InterpretOnly()); \ 775 } else { \ 776 EXPECT_FALSE(instr->InterpretOnly()); \ 777 } \ 778 if (interpreter) { \ 779 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); \ 780 } else { \ 781 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); \ 782 } \ 783 } while (false) 784 785TEST_F(InstrumentationTest, ConfigureStubs_Nothing) { 786 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 787 788 // Check no-op. 789 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 790 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 791} 792 793TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) { 794 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 795 796 // Check we can switch to instrumentation stubs 797 CheckConfigureStubs(kClientOneKey, 798 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 799 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 800 1U); 801 802 // Check we can disable instrumentation. 803 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 804 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 805} 806 807TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) { 808 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 809 810 // Check we can switch to interpreter 811 CheckConfigureStubs(kClientOneKey, 812 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 813 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 814 815 // Check we can disable instrumentation. 816 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 817 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 818} 819 820TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) { 821 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 822 823 // Configure stubs with instrumentation stubs. 824 CheckConfigureStubs(kClientOneKey, 825 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 826 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 827 1U); 828 829 // Configure stubs with interpreter. 830 CheckConfigureStubs(kClientOneKey, 831 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 832 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 833 834 // Check we can disable instrumentation. 835 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 836 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 837} 838 839TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) { 840 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 841 842 // Configure stubs with interpreter. 843 CheckConfigureStubs(kClientOneKey, 844 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 845 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 846 847 // Configure stubs with instrumentation stubs. 848 CheckConfigureStubs(kClientOneKey, 849 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 850 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 851 1U); 852 853 // Check we can disable instrumentation. 854 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 855 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 856} 857 858TEST_F(InstrumentationTest, 859 ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) { 860 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 861 862 // Configure stubs with instrumentation stubs. 863 CheckConfigureStubs(kClientOneKey, 864 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 865 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 866 1U); 867 868 // Configure stubs with interpreter. 869 CheckConfigureStubs(kClientOneKey, 870 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 871 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 872 873 // Configure stubs with instrumentation stubs again. 874 CheckConfigureStubs(kClientOneKey, 875 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 876 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 877 1U); 878 879 // Check we can disable instrumentation. 880 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 881 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 882} 883 884TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) { 885 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 886 887 // Check kInstrumentNothing with two clients. 888 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 889 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 890 891 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 892 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 893} 894 895TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) { 896 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 897 898 // Configure stubs with instrumentation stubs for 1st client. 899 CheckConfigureStubs(kClientOneKey, 900 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 901 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 902 1U); 903 904 // Configure stubs with instrumentation stubs for 2nd client. 905 CheckConfigureStubs(kClientTwoKey, 906 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 907 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 908 2U); 909 910 // 1st client requests instrumentation deactivation but 2nd client still needs 911 // instrumentation stubs. 912 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 913 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 914 1U); 915 916 // 2nd client requests instrumentation deactivation 917 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 918 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 919} 920 921TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) { 922 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 923 924 // Configure stubs with interpreter for 1st client. 925 CheckConfigureStubs(kClientOneKey, 926 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 927 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 928 929 // Configure stubs with interpreter for 2nd client. 930 CheckConfigureStubs(kClientTwoKey, 931 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 932 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U); 933 934 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter. 935 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 936 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 937 938 // 2nd client requests instrumentation deactivation 939 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 940 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 941} 942 943TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) { 944 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 945 946 // Configure stubs with instrumentation stubs for 1st client. 947 CheckConfigureStubs(kClientOneKey, 948 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 949 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 950 1U); 951 952 // Configure stubs with interpreter for 2nd client. 953 CheckConfigureStubs(kClientTwoKey, 954 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 955 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U); 956 957 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter. 958 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 959 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 960 961 // 2nd client requests instrumentation deactivation 962 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 963 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 964} 965 966TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) { 967 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 968 969 // Configure stubs with interpreter for 1st client. 970 CheckConfigureStubs(kClientOneKey, 971 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); 972 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U); 973 974 // Configure stubs with instrumentation stubs for 2nd client. 975 CheckConfigureStubs(kClientTwoKey, 976 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs); 977 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U); 978 979 // 1st client requests instrumentation deactivation but 2nd client still needs 980 // instrumentation stubs. 981 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 982 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs, 983 1U); 984 985 // 2nd client requests instrumentation deactivation 986 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing); 987 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U); 988} 989 990} // namespace instrumentation 991} // namespace art 992