blob: d98d246914f2551bc1d4ff45910cd241929ec3c4 [file] [log] [blame]
Sebastien Hertz0462c4c2015-04-01 16:34:17 +02001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "instrumentation.h"
18
19#include "common_runtime_test.h"
20#include "common_throws.h"
21#include "class_linker-inl.h"
22#include "dex_file.h"
23#include "handle_scope-inl.h"
24#include "jvalue.h"
25#include "runtime.h"
26#include "scoped_thread_state_change.h"
27#include "thread_list.h"
28#include "thread-inl.h"
29
30namespace art {
31namespace instrumentation {
32
33class TestInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
34 public:
35 TestInstrumentationListener()
36 : received_method_enter_event(false), received_method_exit_event(false),
37 received_method_unwind_event(false), received_dex_pc_moved_event(false),
38 received_field_read_event(false), received_field_written_event(false),
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010039 received_exception_caught_event(false), received_backward_branch_event(false),
40 received_invoke_virtual_or_interface_event(false) {}
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020041
42 virtual ~TestInstrumentationListener() {}
43
44 void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
45 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070046 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020047 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070048 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020049 received_method_enter_event = true;
50 }
51
52 void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
53 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070054 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020055 uint32_t dex_pc ATTRIBUTE_UNUSED,
56 const JValue& return_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070057 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020058 received_method_exit_event = true;
59 }
60
61 void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
62 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070063 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020064 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070065 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020066 received_method_unwind_event = true;
67 }
68
69 void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
70 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070071 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020072 uint32_t new_dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070073 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020074 received_dex_pc_moved_event = true;
75 }
76
77 void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
78 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070079 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020080 uint32_t dex_pc ATTRIBUTE_UNUSED,
81 ArtField* field ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070082 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020083 received_field_read_event = true;
84 }
85
86 void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
87 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070088 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020089 uint32_t dex_pc ATTRIBUTE_UNUSED,
90 ArtField* field ATTRIBUTE_UNUSED,
91 const JValue& field_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070092 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020093 received_field_written_event = true;
94 }
95
96 void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
97 mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070098 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020099 received_exception_caught_event = true;
100 }
101
102 void BackwardBranch(Thread* thread ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700103 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200104 int32_t dex_pc_offset ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -0700105 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200106 received_backward_branch_event = true;
107 }
108
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100109 void InvokeVirtualOrInterface(Thread* thread ATTRIBUTE_UNUSED,
110 mirror::Object* this_object ATTRIBUTE_UNUSED,
111 ArtMethod* caller ATTRIBUTE_UNUSED,
112 uint32_t dex_pc ATTRIBUTE_UNUSED,
113 ArtMethod* callee ATTRIBUTE_UNUSED)
114 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
115 received_invoke_virtual_or_interface_event = true;
116 }
117
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200118 void Reset() {
119 received_method_enter_event = false;
120 received_method_exit_event = false;
121 received_method_unwind_event = false;
122 received_dex_pc_moved_event = false;
123 received_field_read_event = false;
124 received_field_written_event = false;
125 received_exception_caught_event = false;
126 received_backward_branch_event = false;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100127 received_invoke_virtual_or_interface_event = false;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200128 }
129
130 bool received_method_enter_event;
131 bool received_method_exit_event;
132 bool received_method_unwind_event;
133 bool received_dex_pc_moved_event;
134 bool received_field_read_event;
135 bool received_field_written_event;
136 bool received_exception_caught_event;
137 bool received_backward_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100138 bool received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200139
140 private:
141 DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
142};
143
144class InstrumentationTest : public CommonRuntimeTest {
145 public:
146 // Unique keys used to test Instrumentation::ConfigureStubs.
147 static constexpr const char* kClientOneKey = "TestClient1";
148 static constexpr const char* kClientTwoKey = "TestClient2";
149
150 void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
151 ScopedObjectAccess soa(Thread::Current());
152 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700153 ScopedThreadSuspension sts(soa.Self(), kSuspended);
154 ScopedSuspendAll ssa("Instrumentation::ConfigureStubs");
155 instr->ConfigureStubs(key, level);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200156 }
157
158 Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
159 return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
160 }
161
162 size_t GetInstrumentationUserCount() {
163 ScopedObjectAccess soa(Thread::Current());
164 return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
165 }
166
167 void TestEvent(uint32_t instrumentation_event) {
168 ScopedObjectAccess soa(Thread::Current());
169 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
170 TestInstrumentationListener listener;
171 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700172 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700173 ScopedSuspendAll ssa("Add instrumentation listener");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200174 instr->AddListener(&listener, instrumentation_event);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200175 }
176
Mathieu Chartiere401d142015-04-22 13:56:20 -0700177 ArtMethod* const event_method = nullptr;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200178 mirror::Object* const event_obj = nullptr;
179 const uint32_t event_dex_pc = 0;
180
181 // Check the listener is registered and is notified of the event.
182 EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
183 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
184 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
185 EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
186
187 listener.Reset();
188 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700189 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700190 ScopedSuspendAll ssa("Remove instrumentation listener");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200191 instr->RemoveListener(&listener, instrumentation_event);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200192 }
193
194 // Check the listener is not registered and is not notified of the event.
195 EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
196 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
197 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
198 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
199 }
200
Mathieu Chartiere401d142015-04-22 13:56:20 -0700201 void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700202 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200203 Runtime* runtime = Runtime::Current();
204 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700205 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700206 ScopedSuspendAll ssa("Single method deoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200207 if (enable_deoptimization) {
208 instrumentation->EnableDeoptimization();
209 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700210 instrumentation->Deoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200211 }
212
Mathieu Chartiere401d142015-04-22 13:56:20 -0700213 void UndeoptimizeMethod(Thread* self, ArtMethod* method,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200214 const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700215 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200216 Runtime* runtime = Runtime::Current();
217 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700218 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700219 ScopedSuspendAll ssa("Single method undeoptimization");
Mathieu Chartiere401d142015-04-22 13:56:20 -0700220 instrumentation->Undeoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200221 if (disable_deoptimization) {
222 instrumentation->DisableDeoptimization(key);
223 }
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200224 }
225
226 void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700227 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200228 Runtime* runtime = Runtime::Current();
229 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700230 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700231 ScopedSuspendAll ssa("Full deoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200232 if (enable_deoptimization) {
233 instrumentation->EnableDeoptimization();
234 }
235 instrumentation->DeoptimizeEverything(key);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200236 }
237
238 void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700239 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200240 Runtime* runtime = Runtime::Current();
241 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700242 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700243 ScopedSuspendAll ssa("Full undeoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200244 instrumentation->UndeoptimizeEverything(key);
245 if (disable_deoptimization) {
246 instrumentation->DisableDeoptimization(key);
247 }
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200248 }
249
250 void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
Mathieu Chartier90443472015-07-16 20:32:27 -0700251 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200252 Runtime* runtime = Runtime::Current();
253 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700254 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700255 ScopedSuspendAll ssa("EnableMethodTracing");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200256 instrumentation->EnableMethodTracing(key, needs_interpreter);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200257 }
258
259 void DisableMethodTracing(Thread* self, const char* key)
Mathieu Chartier90443472015-07-16 20:32:27 -0700260 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200261 Runtime* runtime = Runtime::Current();
262 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700263 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700264 ScopedSuspendAll ssa("EnableMethodTracing");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200265 instrumentation->DisableMethodTracing(key);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200266 }
267
268 private:
269 static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
Mathieu Chartier90443472015-07-16 20:32:27 -0700270 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200271 switch (event_type) {
272 case instrumentation::Instrumentation::kMethodEntered:
273 return instr->HasMethodEntryListeners();
274 case instrumentation::Instrumentation::kMethodExited:
275 return instr->HasMethodExitListeners();
276 case instrumentation::Instrumentation::kMethodUnwind:
277 return instr->HasMethodUnwindListeners();
278 case instrumentation::Instrumentation::kDexPcMoved:
279 return instr->HasDexPcListeners();
280 case instrumentation::Instrumentation::kFieldRead:
281 return instr->HasFieldReadListeners();
282 case instrumentation::Instrumentation::kFieldWritten:
283 return instr->HasFieldWriteListeners();
284 case instrumentation::Instrumentation::kExceptionCaught:
285 return instr->HasExceptionCaughtListeners();
286 case instrumentation::Instrumentation::kBackwardBranch:
287 return instr->HasBackwardBranchListeners();
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100288 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
289 return instr->HasInvokeVirtualOrInterfaceListeners();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200290 default:
291 LOG(FATAL) << "Unknown instrumentation event " << event_type;
292 UNREACHABLE();
293 }
294 }
295
296 static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700297 Thread* self, ArtMethod* method, mirror::Object* obj,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200298 uint32_t dex_pc)
Mathieu Chartier90443472015-07-16 20:32:27 -0700299 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200300 switch (event_type) {
301 case instrumentation::Instrumentation::kMethodEntered:
302 instr->MethodEnterEvent(self, obj, method, dex_pc);
303 break;
304 case instrumentation::Instrumentation::kMethodExited: {
305 JValue value;
306 instr->MethodExitEvent(self, obj, method, dex_pc, value);
307 break;
308 }
309 case instrumentation::Instrumentation::kMethodUnwind:
310 instr->MethodUnwindEvent(self, obj, method, dex_pc);
311 break;
312 case instrumentation::Instrumentation::kDexPcMoved:
313 instr->DexPcMovedEvent(self, obj, method, dex_pc);
314 break;
315 case instrumentation::Instrumentation::kFieldRead:
316 instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
317 break;
318 case instrumentation::Instrumentation::kFieldWritten: {
319 JValue value;
320 instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
321 break;
322 }
323 case instrumentation::Instrumentation::kExceptionCaught: {
324 ThrowArithmeticExceptionDivideByZero();
325 mirror::Throwable* event_exception = self->GetException();
326 instr->ExceptionCaughtEvent(self, event_exception);
327 self->ClearException();
328 break;
329 }
330 case instrumentation::Instrumentation::kBackwardBranch:
331 instr->BackwardBranch(self, method, dex_pc);
332 break;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100333 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
334 instr->InvokeVirtualOrInterface(self, obj, method, dex_pc, method);
335 break;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200336 default:
337 LOG(FATAL) << "Unknown instrumentation event " << event_type;
338 UNREACHABLE();
339 }
340 }
341
342 static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
343 uint32_t event_type) {
344 switch (event_type) {
345 case instrumentation::Instrumentation::kMethodEntered:
346 return listener.received_method_enter_event;
347 case instrumentation::Instrumentation::kMethodExited:
348 return listener.received_method_exit_event;
349 case instrumentation::Instrumentation::kMethodUnwind:
350 return listener.received_method_unwind_event;
351 case instrumentation::Instrumentation::kDexPcMoved:
352 return listener.received_dex_pc_moved_event;
353 case instrumentation::Instrumentation::kFieldRead:
354 return listener.received_field_read_event;
355 case instrumentation::Instrumentation::kFieldWritten:
356 return listener.received_field_written_event;
357 case instrumentation::Instrumentation::kExceptionCaught:
358 return listener.received_exception_caught_event;
359 case instrumentation::Instrumentation::kBackwardBranch:
360 return listener.received_backward_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100361 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
362 return listener.received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200363 default:
364 LOG(FATAL) << "Unknown instrumentation event " << event_type;
365 UNREACHABLE();
366 }
367 }
368};
369
370TEST_F(InstrumentationTest, NoInstrumentation) {
371 ScopedObjectAccess soa(Thread::Current());
372 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
373 ASSERT_NE(instr, nullptr);
374
375 EXPECT_FALSE(instr->AreExitStubsInstalled());
376 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
377 EXPECT_FALSE(instr->IsActive());
378 EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
379
380 // Test interpreter table is the default one.
381 EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
382
383 // Check there is no registered listener.
384 EXPECT_FALSE(instr->HasDexPcListeners());
385 EXPECT_FALSE(instr->HasExceptionCaughtListeners());
386 EXPECT_FALSE(instr->HasFieldReadListeners());
387 EXPECT_FALSE(instr->HasFieldWriteListeners());
388 EXPECT_FALSE(instr->HasMethodEntryListeners());
389 EXPECT_FALSE(instr->HasMethodExitListeners());
390 EXPECT_FALSE(instr->IsActive());
391}
392
393// Test instrumentation listeners for each event.
394TEST_F(InstrumentationTest, MethodEntryEvent) {
395 TestEvent(instrumentation::Instrumentation::kMethodEntered);
396}
397
398TEST_F(InstrumentationTest, MethodExitEvent) {
399 TestEvent(instrumentation::Instrumentation::kMethodExited);
400}
401
402TEST_F(InstrumentationTest, MethodUnwindEvent) {
403 TestEvent(instrumentation::Instrumentation::kMethodUnwind);
404}
405
406TEST_F(InstrumentationTest, DexPcMovedEvent) {
407 TestEvent(instrumentation::Instrumentation::kDexPcMoved);
408}
409
410TEST_F(InstrumentationTest, FieldReadEvent) {
411 TestEvent(instrumentation::Instrumentation::kFieldRead);
412}
413
414TEST_F(InstrumentationTest, FieldWriteEvent) {
415 TestEvent(instrumentation::Instrumentation::kFieldWritten);
416}
417
418TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
419 TestEvent(instrumentation::Instrumentation::kExceptionCaught);
420}
421
422TEST_F(InstrumentationTest, BackwardBranchEvent) {
423 TestEvent(instrumentation::Instrumentation::kBackwardBranch);
424}
425
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100426TEST_F(InstrumentationTest, InvokeVirtualOrInterfaceEvent) {
427 TestEvent(instrumentation::Instrumentation::kInvokeVirtualOrInterface);
428}
429
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200430TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
431 ScopedObjectAccess soa(Thread::Current());
432 jobject class_loader = LoadDex("Instrumentation");
433 Runtime* const runtime = Runtime::Current();
434 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
435 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700436 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200437 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
438 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
439 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700440 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
441 sizeof(void*));
442 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200443
444 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700445 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200446
447 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
448
449 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
450 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700451 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200452
453 constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
454 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
455
456 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700457 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200458}
459
460TEST_F(InstrumentationTest, FullDeoptimization) {
461 ScopedObjectAccess soa(Thread::Current());
462 Runtime* const runtime = Runtime::Current();
463 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
464 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
465
466 constexpr const char* instrumentation_key = "FullDeoptimization";
467 DeoptimizeEverything(soa.Self(), instrumentation_key, true);
468
469 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
470 EXPECT_TRUE(instr->AreExitStubsInstalled());
471
472 UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
473
474 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
475}
476
477TEST_F(InstrumentationTest, MixedDeoptimization) {
478 ScopedObjectAccess soa(Thread::Current());
479 jobject class_loader = LoadDex("Instrumentation");
480 Runtime* const runtime = Runtime::Current();
481 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
482 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700483 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200484 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
485 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
486 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700487 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
488 sizeof(void*));
489 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200490
491 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700492 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200493
494 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
495 // Deoptimizing a method does not change instrumentation level.
496 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
497 GetCurrentInstrumentationLevel());
498 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
499 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700500 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200501
502 constexpr const char* instrumentation_key = "MixedDeoptimization";
503 DeoptimizeEverything(soa.Self(), instrumentation_key, false);
504 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
505 GetCurrentInstrumentationLevel());
506 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
507 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700508 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200509
510 UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
511 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
512 GetCurrentInstrumentationLevel());
513 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
514 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700515 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200516
517 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
518 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
519 GetCurrentInstrumentationLevel());
520 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700521 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200522}
523
524TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
525 ScopedObjectAccess soa(Thread::Current());
526 Runtime* const runtime = Runtime::Current();
527 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
528 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
529
530 constexpr const char* instrumentation_key = "MethodTracing";
531 EnableMethodTracing(soa.Self(), instrumentation_key, true);
532 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
533 GetCurrentInstrumentationLevel());
534 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
535 EXPECT_TRUE(instr->AreExitStubsInstalled());
536
537 DisableMethodTracing(soa.Self(), instrumentation_key);
538 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
539 GetCurrentInstrumentationLevel());
540 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
541}
542
543TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
544 ScopedObjectAccess soa(Thread::Current());
545 Runtime* const runtime = Runtime::Current();
546 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
547 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
548
549 constexpr const char* instrumentation_key = "MethodTracing";
550 EnableMethodTracing(soa.Self(), instrumentation_key, false);
551 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
552 GetCurrentInstrumentationLevel());
553 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
554 EXPECT_TRUE(instr->AreExitStubsInstalled());
555
556 DisableMethodTracing(soa.Self(), instrumentation_key);
557 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
558 GetCurrentInstrumentationLevel());
559 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
560}
561
562// We use a macro to print the line number where the test is failing.
563#define CHECK_INSTRUMENTATION(_level, _user_count) \
564 do { \
565 Instrumentation* const instr = Runtime::Current()->GetInstrumentation(); \
566 bool interpreter = \
567 (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); \
568 EXPECT_EQ(_level, GetCurrentInstrumentationLevel()); \
569 EXPECT_EQ(_user_count, GetInstrumentationUserCount()); \
570 if (instr->IsForcedInterpretOnly()) { \
571 EXPECT_TRUE(instr->InterpretOnly()); \
572 } else if (interpreter) { \
573 EXPECT_TRUE(instr->InterpretOnly()); \
574 } else { \
575 EXPECT_FALSE(instr->InterpretOnly()); \
576 } \
577 if (interpreter) { \
578 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); \
579 } else { \
580 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); \
581 } \
582 } while (false)
583
584TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
585 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
586
587 // Check no-op.
588 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
589 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
590}
591
592TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
593 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
594
595 // Check we can switch to instrumentation stubs
596 CheckConfigureStubs(kClientOneKey,
597 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
598 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
599 1U);
600
601 // Check we can disable instrumentation.
602 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
603 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
604}
605
606TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
607 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
608
609 // Check we can switch to interpreter
610 CheckConfigureStubs(kClientOneKey,
611 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
612 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
613
614 // Check we can disable instrumentation.
615 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
616 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
617}
618
619TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
620 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
621
622 // Configure stubs with instrumentation stubs.
623 CheckConfigureStubs(kClientOneKey,
624 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
625 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
626 1U);
627
628 // Configure stubs with interpreter.
629 CheckConfigureStubs(kClientOneKey,
630 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
631 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
632
633 // Check we can disable instrumentation.
634 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
635 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
636}
637
638TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
639 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
640
641 // Configure stubs with interpreter.
642 CheckConfigureStubs(kClientOneKey,
643 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
644 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
645
646 // Configure stubs with instrumentation stubs.
647 CheckConfigureStubs(kClientOneKey,
648 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
649 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
650 1U);
651
652 // Check we can disable instrumentation.
653 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
654 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
655}
656
657TEST_F(InstrumentationTest,
658 ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
659 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
660
661 // Configure stubs with instrumentation stubs.
662 CheckConfigureStubs(kClientOneKey,
663 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
664 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
665 1U);
666
667 // Configure stubs with interpreter.
668 CheckConfigureStubs(kClientOneKey,
669 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
670 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
671
672 // Configure stubs with instrumentation stubs again.
673 CheckConfigureStubs(kClientOneKey,
674 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
675 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
676 1U);
677
678 // Check we can disable instrumentation.
679 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
680 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
681}
682
683TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
684 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
685
686 // Check kInstrumentNothing with two clients.
687 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
688 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
689
690 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
691 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
692}
693
694TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
695 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
696
697 // Configure stubs with instrumentation stubs for 1st client.
698 CheckConfigureStubs(kClientOneKey,
699 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
700 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
701 1U);
702
703 // Configure stubs with instrumentation stubs for 2nd client.
704 CheckConfigureStubs(kClientTwoKey,
705 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
706 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
707 2U);
708
709 // 1st client requests instrumentation deactivation but 2nd client still needs
710 // instrumentation stubs.
711 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
712 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
713 1U);
714
715 // 2nd client requests instrumentation deactivation
716 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
717 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
718}
719
720TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
721 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
722
723 // Configure stubs with interpreter for 1st client.
724 CheckConfigureStubs(kClientOneKey,
725 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
726 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
727
728 // Configure stubs with interpreter for 2nd client.
729 CheckConfigureStubs(kClientTwoKey,
730 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
731 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
732
733 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
734 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
735 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
736
737 // 2nd client requests instrumentation deactivation
738 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
739 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
740}
741
742TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
743 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
744
745 // Configure stubs with instrumentation stubs for 1st client.
746 CheckConfigureStubs(kClientOneKey,
747 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
748 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
749 1U);
750
751 // Configure stubs with interpreter for 2nd client.
752 CheckConfigureStubs(kClientTwoKey,
753 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
754 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
755
756 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
757 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
758 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
759
760 // 2nd client requests instrumentation deactivation
761 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
762 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
763}
764
765TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
766 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
767
768 // Configure stubs with interpreter for 1st client.
769 CheckConfigureStubs(kClientOneKey,
770 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
771 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
772
773 // Configure stubs with instrumentation stubs for 2nd client.
774 CheckConfigureStubs(kClientTwoKey,
775 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
776 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
777
778 // 1st client requests instrumentation deactivation but 2nd client still needs
779 // instrumentation stubs.
780 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
781 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
782 1U);
783
784 // 2nd client requests instrumentation deactivation
785 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
786 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
787}
788
789} // namespace instrumentation
790} // namespace art