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