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