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