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