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