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