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:
TestInstrumentationListener()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
~TestInstrumentationListener()44 virtual ~TestInstrumentationListener() {}
45
MethodEntered(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED)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
MethodExited(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,const JValue & return_value ATTRIBUTE_UNUSED)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
MethodUnwind(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED)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
DexPcMoved(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t new_dex_pc ATTRIBUTE_UNUSED)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
FieldRead(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,ArtField * field ATTRIBUTE_UNUSED)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
FieldWritten(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,ArtField * field ATTRIBUTE_UNUSED,const JValue & field_value ATTRIBUTE_UNUSED)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
ExceptionCaught(Thread * thread ATTRIBUTE_UNUSED,mirror::Throwable * exception_object ATTRIBUTE_UNUSED)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
Branch(Thread * thread ATTRIBUTE_UNUSED,ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,int32_t dex_pc_offset ATTRIBUTE_UNUSED)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
InvokeVirtualOrInterface(Thread * thread ATTRIBUTE_UNUSED,mirror::Object * this_object ATTRIBUTE_UNUSED,ArtMethod * caller ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,ArtMethod * callee ATTRIBUTE_UNUSED)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
Reset()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
CheckConfigureStubs(const char * key,Instrumentation::InstrumentationLevel level)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
GetCurrentInstrumentationLevel()164 Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
165 return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
166 }
167
GetInstrumentationUserCount()168 size_t GetInstrumentationUserCount() {
169 ScopedObjectAccess soa(Thread::Current());
170 return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
171 }
172
TestEvent(uint32_t instrumentation_event)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
DeoptimizeMethod(Thread * self,ArtMethod * method,bool enable_deoptimization)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
UndeoptimizeMethod(Thread * self,ArtMethod * method,const char * key,bool disable_deoptimization)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
DeoptimizeEverything(Thread * self,const char * key,bool enable_deoptimization)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
UndeoptimizeEverything(Thread * self,const char * key,bool disable_deoptimization)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
EnableMethodTracing(Thread * self,const char * key,bool needs_interpreter)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
DisableMethodTracing(Thread * self,const char * key)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:
HasEventListener(const instrumentation::Instrumentation * instr,uint32_t event_type)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
ReportEvent(const instrumentation::Instrumentation * instr,uint32_t event_type,Thread * self,ArtMethod * method,mirror::Object * obj,uint32_t dex_pc)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
DidListenerReceiveEvent(const TestInstrumentationListener & listener,uint32_t event_type)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
TEST_F(InstrumentationTest,NoInstrumentation)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.
TEST_F(InstrumentationTest,MethodEntryEvent)418 TEST_F(InstrumentationTest, MethodEntryEvent) {
419 TestEvent(instrumentation::Instrumentation::kMethodEntered);
420 }
421
TEST_F(InstrumentationTest,MethodExitEvent)422 TEST_F(InstrumentationTest, MethodExitEvent) {
423 TestEvent(instrumentation::Instrumentation::kMethodExited);
424 }
425
TEST_F(InstrumentationTest,MethodUnwindEvent)426 TEST_F(InstrumentationTest, MethodUnwindEvent) {
427 TestEvent(instrumentation::Instrumentation::kMethodUnwind);
428 }
429
TEST_F(InstrumentationTest,DexPcMovedEvent)430 TEST_F(InstrumentationTest, DexPcMovedEvent) {
431 TestEvent(instrumentation::Instrumentation::kDexPcMoved);
432 }
433
TEST_F(InstrumentationTest,FieldReadEvent)434 TEST_F(InstrumentationTest, FieldReadEvent) {
435 TestEvent(instrumentation::Instrumentation::kFieldRead);
436 }
437
TEST_F(InstrumentationTest,FieldWriteEvent)438 TEST_F(InstrumentationTest, FieldWriteEvent) {
439 TestEvent(instrumentation::Instrumentation::kFieldWritten);
440 }
441
TEST_F(InstrumentationTest,ExceptionCaughtEvent)442 TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
443 TestEvent(instrumentation::Instrumentation::kExceptionCaught);
444 }
445
TEST_F(InstrumentationTest,BranchEvent)446 TEST_F(InstrumentationTest, BranchEvent) {
447 TestEvent(instrumentation::Instrumentation::kBranch);
448 }
449
TEST_F(InstrumentationTest,InvokeVirtualOrInterfaceEvent)450 TEST_F(InstrumentationTest, InvokeVirtualOrInterfaceEvent) {
451 TestEvent(instrumentation::Instrumentation::kInvokeVirtualOrInterface);
452 }
453
TEST_F(InstrumentationTest,DeoptimizeDirectMethod)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
TEST_F(InstrumentationTest,FullDeoptimization)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
TEST_F(InstrumentationTest,MixedDeoptimization)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
TEST_F(InstrumentationTest,MethodTracing_Interpreter)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
TEST_F(InstrumentationTest,MethodTracing_InstrumentationEntryExitStubs)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
TEST_F(InstrumentationTest,ConfigureStubs_Nothing)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
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubs)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
TEST_F(InstrumentationTest,ConfigureStubs_Interpreter)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
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreter)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
TEST_F(InstrumentationTest,ConfigureStubs_InterpreterToInstrumentationStubs)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
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs)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
TEST_F(InstrumentationTest,MultiConfigureStubs_Nothing)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
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubs)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
TEST_F(InstrumentationTest,MultiConfigureStubs_Interpreter)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
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubsThenInterpreter)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
TEST_F(InstrumentationTest,MultiConfigureStubs_InterpreterThenInstrumentationStubs)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