blob: e4688a21ddb10c5445ffb46624fc4b992ddae1de [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"
Mathieu Chartieraa516822015-10-02 15:53:37 -070023#include "gc/scoped_gc_critical_section.h"
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020024#include "handle_scope-inl.h"
25#include "jvalue.h"
26#include "runtime.h"
27#include "scoped_thread_state_change.h"
28#include "thread_list.h"
29#include "thread-inl.h"
30
31namespace art {
32namespace instrumentation {
33
34class TestInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
35 public:
36 TestInstrumentationListener()
37 : received_method_enter_event(false), received_method_exit_event(false),
38 received_method_unwind_event(false), received_dex_pc_moved_event(false),
39 received_field_read_event(false), received_field_written_event(false),
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010040 received_exception_caught_event(false), received_backward_branch_event(false),
41 received_invoke_virtual_or_interface_event(false) {}
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020042
43 virtual ~TestInstrumentationListener() {}
44
45 void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
46 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070047 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020048 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070049 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020050 received_method_enter_event = true;
51 }
52
53 void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
54 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070055 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020056 uint32_t dex_pc ATTRIBUTE_UNUSED,
57 const JValue& return_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070058 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020059 received_method_exit_event = true;
60 }
61
62 void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
63 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070064 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020065 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070066 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020067 received_method_unwind_event = true;
68 }
69
70 void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
71 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070072 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020073 uint32_t new_dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070074 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020075 received_dex_pc_moved_event = true;
76 }
77
78 void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
79 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070080 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020081 uint32_t dex_pc ATTRIBUTE_UNUSED,
82 ArtField* field ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070083 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020084 received_field_read_event = true;
85 }
86
87 void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
88 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070089 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020090 uint32_t dex_pc ATTRIBUTE_UNUSED,
91 ArtField* field ATTRIBUTE_UNUSED,
92 const JValue& field_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070093 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020094 received_field_written_event = true;
95 }
96
97 void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
98 mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070099 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200100 received_exception_caught_event = true;
101 }
102
103 void BackwardBranch(Thread* thread ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700104 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200105 int32_t dex_pc_offset ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -0700106 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200107 received_backward_branch_event = true;
108 }
109
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100110 void InvokeVirtualOrInterface(Thread* thread ATTRIBUTE_UNUSED,
111 mirror::Object* this_object ATTRIBUTE_UNUSED,
112 ArtMethod* caller ATTRIBUTE_UNUSED,
113 uint32_t dex_pc ATTRIBUTE_UNUSED,
114 ArtMethod* callee ATTRIBUTE_UNUSED)
115 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
116 received_invoke_virtual_or_interface_event = true;
117 }
118
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200119 void Reset() {
120 received_method_enter_event = false;
121 received_method_exit_event = false;
122 received_method_unwind_event = false;
123 received_dex_pc_moved_event = false;
124 received_field_read_event = false;
125 received_field_written_event = false;
126 received_exception_caught_event = false;
127 received_backward_branch_event = false;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100128 received_invoke_virtual_or_interface_event = false;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200129 }
130
131 bool received_method_enter_event;
132 bool received_method_exit_event;
133 bool received_method_unwind_event;
134 bool received_dex_pc_moved_event;
135 bool received_field_read_event;
136 bool received_field_written_event;
137 bool received_exception_caught_event;
138 bool received_backward_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100139 bool received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200140
141 private:
142 DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
143};
144
145class InstrumentationTest : public CommonRuntimeTest {
146 public:
147 // Unique keys used to test Instrumentation::ConfigureStubs.
148 static constexpr const char* kClientOneKey = "TestClient1";
149 static constexpr const char* kClientTwoKey = "TestClient2";
150
151 void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
152 ScopedObjectAccess soa(Thread::Current());
153 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700154 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700155 gc::ScopedGCCriticalSection gcs(soa.Self(),
156 gc::kGcCauseInstrumentation,
157 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700158 ScopedSuspendAll ssa("Instrumentation::ConfigureStubs");
159 instr->ConfigureStubs(key, level);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200160 }
161
162 Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
163 return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
164 }
165
166 size_t GetInstrumentationUserCount() {
167 ScopedObjectAccess soa(Thread::Current());
168 return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
169 }
170
171 void TestEvent(uint32_t instrumentation_event) {
172 ScopedObjectAccess soa(Thread::Current());
173 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
174 TestInstrumentationListener listener;
175 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700176 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700177 ScopedSuspendAll ssa("Add instrumentation listener");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200178 instr->AddListener(&listener, instrumentation_event);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200179 }
180
Mathieu Chartiere401d142015-04-22 13:56:20 -0700181 ArtMethod* const event_method = nullptr;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200182 mirror::Object* const event_obj = nullptr;
183 const uint32_t event_dex_pc = 0;
184
185 // Check the listener is registered and is notified of the event.
186 EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
187 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
188 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
189 EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
190
191 listener.Reset();
192 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700193 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700194 ScopedSuspendAll ssa("Remove instrumentation listener");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200195 instr->RemoveListener(&listener, instrumentation_event);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200196 }
197
198 // Check the listener is not registered and is not notified of the event.
199 EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
200 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
201 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
202 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
203 }
204
Mathieu Chartiere401d142015-04-22 13:56:20 -0700205 void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700206 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200207 Runtime* runtime = Runtime::Current();
208 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700209 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700210 gc::ScopedGCCriticalSection gcs(self,
211 gc::kGcCauseInstrumentation,
212 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700213 ScopedSuspendAll ssa("Single method deoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200214 if (enable_deoptimization) {
215 instrumentation->EnableDeoptimization();
216 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700217 instrumentation->Deoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200218 }
219
Mathieu Chartiere401d142015-04-22 13:56:20 -0700220 void UndeoptimizeMethod(Thread* self, ArtMethod* method,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200221 const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700222 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200223 Runtime* runtime = Runtime::Current();
224 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700225 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700226 gc::ScopedGCCriticalSection gcs(self,
227 gc::kGcCauseInstrumentation,
228 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700229 ScopedSuspendAll ssa("Single method undeoptimization");
Mathieu Chartiere401d142015-04-22 13:56:20 -0700230 instrumentation->Undeoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200231 if (disable_deoptimization) {
232 instrumentation->DisableDeoptimization(key);
233 }
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200234 }
235
236 void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700237 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200238 Runtime* runtime = Runtime::Current();
239 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700240 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700241 gc::ScopedGCCriticalSection gcs(self,
242 gc::kGcCauseInstrumentation,
243 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700244 ScopedSuspendAll ssa("Full deoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200245 if (enable_deoptimization) {
246 instrumentation->EnableDeoptimization();
247 }
248 instrumentation->DeoptimizeEverything(key);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200249 }
250
251 void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700252 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200253 Runtime* runtime = Runtime::Current();
254 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700255 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700256 gc::ScopedGCCriticalSection gcs(self,
257 gc::kGcCauseInstrumentation,
258 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700259 ScopedSuspendAll ssa("Full undeoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200260 instrumentation->UndeoptimizeEverything(key);
261 if (disable_deoptimization) {
262 instrumentation->DisableDeoptimization(key);
263 }
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200264 }
265
266 void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
Mathieu Chartier90443472015-07-16 20:32:27 -0700267 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200268 Runtime* runtime = Runtime::Current();
269 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700270 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700271 gc::ScopedGCCriticalSection gcs(self,
272 gc::kGcCauseInstrumentation,
273 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700274 ScopedSuspendAll ssa("EnableMethodTracing");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200275 instrumentation->EnableMethodTracing(key, needs_interpreter);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200276 }
277
278 void DisableMethodTracing(Thread* self, const char* key)
Mathieu Chartier90443472015-07-16 20:32:27 -0700279 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200280 Runtime* runtime = Runtime::Current();
281 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700282 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700283 gc::ScopedGCCriticalSection gcs(self,
284 gc::kGcCauseInstrumentation,
285 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700286 ScopedSuspendAll ssa("EnableMethodTracing");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200287 instrumentation->DisableMethodTracing(key);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200288 }
289
290 private:
291 static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
Mathieu Chartier90443472015-07-16 20:32:27 -0700292 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200293 switch (event_type) {
294 case instrumentation::Instrumentation::kMethodEntered:
295 return instr->HasMethodEntryListeners();
296 case instrumentation::Instrumentation::kMethodExited:
297 return instr->HasMethodExitListeners();
298 case instrumentation::Instrumentation::kMethodUnwind:
299 return instr->HasMethodUnwindListeners();
300 case instrumentation::Instrumentation::kDexPcMoved:
301 return instr->HasDexPcListeners();
302 case instrumentation::Instrumentation::kFieldRead:
303 return instr->HasFieldReadListeners();
304 case instrumentation::Instrumentation::kFieldWritten:
305 return instr->HasFieldWriteListeners();
306 case instrumentation::Instrumentation::kExceptionCaught:
307 return instr->HasExceptionCaughtListeners();
308 case instrumentation::Instrumentation::kBackwardBranch:
309 return instr->HasBackwardBranchListeners();
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100310 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
311 return instr->HasInvokeVirtualOrInterfaceListeners();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200312 default:
313 LOG(FATAL) << "Unknown instrumentation event " << event_type;
314 UNREACHABLE();
315 }
316 }
317
318 static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700319 Thread* self, ArtMethod* method, mirror::Object* obj,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200320 uint32_t dex_pc)
Mathieu Chartier90443472015-07-16 20:32:27 -0700321 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200322 switch (event_type) {
323 case instrumentation::Instrumentation::kMethodEntered:
324 instr->MethodEnterEvent(self, obj, method, dex_pc);
325 break;
326 case instrumentation::Instrumentation::kMethodExited: {
327 JValue value;
328 instr->MethodExitEvent(self, obj, method, dex_pc, value);
329 break;
330 }
331 case instrumentation::Instrumentation::kMethodUnwind:
332 instr->MethodUnwindEvent(self, obj, method, dex_pc);
333 break;
334 case instrumentation::Instrumentation::kDexPcMoved:
335 instr->DexPcMovedEvent(self, obj, method, dex_pc);
336 break;
337 case instrumentation::Instrumentation::kFieldRead:
338 instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
339 break;
340 case instrumentation::Instrumentation::kFieldWritten: {
341 JValue value;
342 instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
343 break;
344 }
345 case instrumentation::Instrumentation::kExceptionCaught: {
346 ThrowArithmeticExceptionDivideByZero();
347 mirror::Throwable* event_exception = self->GetException();
348 instr->ExceptionCaughtEvent(self, event_exception);
349 self->ClearException();
350 break;
351 }
352 case instrumentation::Instrumentation::kBackwardBranch:
353 instr->BackwardBranch(self, method, dex_pc);
354 break;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100355 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
356 instr->InvokeVirtualOrInterface(self, obj, method, dex_pc, method);
357 break;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200358 default:
359 LOG(FATAL) << "Unknown instrumentation event " << event_type;
360 UNREACHABLE();
361 }
362 }
363
364 static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
365 uint32_t event_type) {
366 switch (event_type) {
367 case instrumentation::Instrumentation::kMethodEntered:
368 return listener.received_method_enter_event;
369 case instrumentation::Instrumentation::kMethodExited:
370 return listener.received_method_exit_event;
371 case instrumentation::Instrumentation::kMethodUnwind:
372 return listener.received_method_unwind_event;
373 case instrumentation::Instrumentation::kDexPcMoved:
374 return listener.received_dex_pc_moved_event;
375 case instrumentation::Instrumentation::kFieldRead:
376 return listener.received_field_read_event;
377 case instrumentation::Instrumentation::kFieldWritten:
378 return listener.received_field_written_event;
379 case instrumentation::Instrumentation::kExceptionCaught:
380 return listener.received_exception_caught_event;
381 case instrumentation::Instrumentation::kBackwardBranch:
382 return listener.received_backward_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100383 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
384 return listener.received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200385 default:
386 LOG(FATAL) << "Unknown instrumentation event " << event_type;
387 UNREACHABLE();
388 }
389 }
390};
391
392TEST_F(InstrumentationTest, NoInstrumentation) {
393 ScopedObjectAccess soa(Thread::Current());
394 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
395 ASSERT_NE(instr, nullptr);
396
397 EXPECT_FALSE(instr->AreExitStubsInstalled());
398 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
399 EXPECT_FALSE(instr->IsActive());
400 EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
401
402 // Test interpreter table is the default one.
403 EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
404
405 // Check there is no registered listener.
406 EXPECT_FALSE(instr->HasDexPcListeners());
407 EXPECT_FALSE(instr->HasExceptionCaughtListeners());
408 EXPECT_FALSE(instr->HasFieldReadListeners());
409 EXPECT_FALSE(instr->HasFieldWriteListeners());
410 EXPECT_FALSE(instr->HasMethodEntryListeners());
411 EXPECT_FALSE(instr->HasMethodExitListeners());
412 EXPECT_FALSE(instr->IsActive());
413}
414
415// Test instrumentation listeners for each event.
416TEST_F(InstrumentationTest, MethodEntryEvent) {
417 TestEvent(instrumentation::Instrumentation::kMethodEntered);
418}
419
420TEST_F(InstrumentationTest, MethodExitEvent) {
421 TestEvent(instrumentation::Instrumentation::kMethodExited);
422}
423
424TEST_F(InstrumentationTest, MethodUnwindEvent) {
425 TestEvent(instrumentation::Instrumentation::kMethodUnwind);
426}
427
428TEST_F(InstrumentationTest, DexPcMovedEvent) {
429 TestEvent(instrumentation::Instrumentation::kDexPcMoved);
430}
431
432TEST_F(InstrumentationTest, FieldReadEvent) {
433 TestEvent(instrumentation::Instrumentation::kFieldRead);
434}
435
436TEST_F(InstrumentationTest, FieldWriteEvent) {
437 TestEvent(instrumentation::Instrumentation::kFieldWritten);
438}
439
440TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
441 TestEvent(instrumentation::Instrumentation::kExceptionCaught);
442}
443
444TEST_F(InstrumentationTest, BackwardBranchEvent) {
445 TestEvent(instrumentation::Instrumentation::kBackwardBranch);
446}
447
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100448TEST_F(InstrumentationTest, InvokeVirtualOrInterfaceEvent) {
449 TestEvent(instrumentation::Instrumentation::kInvokeVirtualOrInterface);
450}
451
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200452TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
453 ScopedObjectAccess soa(Thread::Current());
454 jobject class_loader = LoadDex("Instrumentation");
455 Runtime* const runtime = Runtime::Current();
456 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
457 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700458 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200459 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
460 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
461 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700462 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
463 sizeof(void*));
464 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200465
466 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700467 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200468
469 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
470
471 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
472 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700473 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200474
475 constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
476 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
477
478 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700479 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200480}
481
482TEST_F(InstrumentationTest, FullDeoptimization) {
483 ScopedObjectAccess soa(Thread::Current());
484 Runtime* const runtime = Runtime::Current();
485 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
486 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
487
488 constexpr const char* instrumentation_key = "FullDeoptimization";
489 DeoptimizeEverything(soa.Self(), instrumentation_key, true);
490
491 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
492 EXPECT_TRUE(instr->AreExitStubsInstalled());
493
494 UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
495
496 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
497}
498
499TEST_F(InstrumentationTest, MixedDeoptimization) {
500 ScopedObjectAccess soa(Thread::Current());
501 jobject class_loader = LoadDex("Instrumentation");
502 Runtime* const runtime = Runtime::Current();
503 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
504 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700505 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200506 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
507 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
508 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700509 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
510 sizeof(void*));
511 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200512
513 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700514 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200515
516 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
517 // Deoptimizing a method does not change instrumentation level.
518 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
519 GetCurrentInstrumentationLevel());
520 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
521 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700522 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200523
524 constexpr const char* instrumentation_key = "MixedDeoptimization";
525 DeoptimizeEverything(soa.Self(), instrumentation_key, false);
526 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
527 GetCurrentInstrumentationLevel());
528 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
529 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700530 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200531
532 UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
533 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
534 GetCurrentInstrumentationLevel());
535 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
536 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700537 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200538
539 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
540 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
541 GetCurrentInstrumentationLevel());
542 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700543 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200544}
545
546TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
547 ScopedObjectAccess soa(Thread::Current());
548 Runtime* const runtime = Runtime::Current();
549 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
550 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
551
552 constexpr const char* instrumentation_key = "MethodTracing";
553 EnableMethodTracing(soa.Self(), instrumentation_key, true);
554 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
555 GetCurrentInstrumentationLevel());
556 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
557 EXPECT_TRUE(instr->AreExitStubsInstalled());
558
559 DisableMethodTracing(soa.Self(), instrumentation_key);
560 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
561 GetCurrentInstrumentationLevel());
562 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
563}
564
565TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
566 ScopedObjectAccess soa(Thread::Current());
567 Runtime* const runtime = Runtime::Current();
568 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
569 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
570
571 constexpr const char* instrumentation_key = "MethodTracing";
572 EnableMethodTracing(soa.Self(), instrumentation_key, false);
573 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
574 GetCurrentInstrumentationLevel());
575 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
576 EXPECT_TRUE(instr->AreExitStubsInstalled());
577
578 DisableMethodTracing(soa.Self(), instrumentation_key);
579 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
580 GetCurrentInstrumentationLevel());
581 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
582}
583
584// We use a macro to print the line number where the test is failing.
585#define CHECK_INSTRUMENTATION(_level, _user_count) \
586 do { \
587 Instrumentation* const instr = Runtime::Current()->GetInstrumentation(); \
588 bool interpreter = \
589 (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); \
590 EXPECT_EQ(_level, GetCurrentInstrumentationLevel()); \
591 EXPECT_EQ(_user_count, GetInstrumentationUserCount()); \
592 if (instr->IsForcedInterpretOnly()) { \
593 EXPECT_TRUE(instr->InterpretOnly()); \
594 } else if (interpreter) { \
595 EXPECT_TRUE(instr->InterpretOnly()); \
596 } else { \
597 EXPECT_FALSE(instr->InterpretOnly()); \
598 } \
599 if (interpreter) { \
600 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); \
601 } else { \
602 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); \
603 } \
604 } while (false)
605
606TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
607 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
608
609 // Check no-op.
610 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
611 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
612}
613
614TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
615 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
616
617 // Check we can switch to instrumentation stubs
618 CheckConfigureStubs(kClientOneKey,
619 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
620 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
621 1U);
622
623 // Check we can disable instrumentation.
624 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
625 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
626}
627
628TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
629 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
630
631 // Check we can switch to interpreter
632 CheckConfigureStubs(kClientOneKey,
633 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
634 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
635
636 // Check we can disable instrumentation.
637 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
638 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
639}
640
641TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
642 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
643
644 // Configure stubs with instrumentation stubs.
645 CheckConfigureStubs(kClientOneKey,
646 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
647 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
648 1U);
649
650 // Configure stubs with interpreter.
651 CheckConfigureStubs(kClientOneKey,
652 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
653 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
654
655 // Check we can disable instrumentation.
656 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
657 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
658}
659
660TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
661 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
662
663 // Configure stubs with interpreter.
664 CheckConfigureStubs(kClientOneKey,
665 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
666 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
667
668 // Configure stubs with instrumentation stubs.
669 CheckConfigureStubs(kClientOneKey,
670 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
671 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
672 1U);
673
674 // Check we can disable instrumentation.
675 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
676 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
677}
678
679TEST_F(InstrumentationTest,
680 ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
681 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
682
683 // Configure stubs with instrumentation stubs.
684 CheckConfigureStubs(kClientOneKey,
685 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
686 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
687 1U);
688
689 // Configure stubs with interpreter.
690 CheckConfigureStubs(kClientOneKey,
691 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
692 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
693
694 // Configure stubs with instrumentation stubs again.
695 CheckConfigureStubs(kClientOneKey,
696 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
697 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
698 1U);
699
700 // Check we can disable instrumentation.
701 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
702 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
703}
704
705TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
706 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
707
708 // Check kInstrumentNothing with two clients.
709 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
710 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
711
712 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
713 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
714}
715
716TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
717 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
718
719 // Configure stubs with instrumentation stubs for 1st client.
720 CheckConfigureStubs(kClientOneKey,
721 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
722 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
723 1U);
724
725 // Configure stubs with instrumentation stubs for 2nd client.
726 CheckConfigureStubs(kClientTwoKey,
727 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
728 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
729 2U);
730
731 // 1st client requests instrumentation deactivation but 2nd client still needs
732 // instrumentation stubs.
733 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
734 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
735 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_Interpreter) {
743 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
744
745 // Configure stubs with interpreter for 1st client.
746 CheckConfigureStubs(kClientOneKey,
747 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
748 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
749
750 // Configure stubs with interpreter for 2nd client.
751 CheckConfigureStubs(kClientTwoKey,
752 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
753 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
754
755 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
756 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
757 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
758
759 // 2nd client requests instrumentation deactivation
760 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
761 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
762}
763
764TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
765 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
766
767 // Configure stubs with instrumentation stubs for 1st client.
768 CheckConfigureStubs(kClientOneKey,
769 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
770 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
771 1U);
772
773 // Configure stubs with interpreter for 2nd client.
774 CheckConfigureStubs(kClientTwoKey,
775 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
776 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
777
778 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
779 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
780 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
781
782 // 2nd client requests instrumentation deactivation
783 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
784 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
785}
786
787TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
788 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
789
790 // Configure stubs with interpreter for 1st client.
791 CheckConfigureStubs(kClientOneKey,
792 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
793 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
794
795 // Configure stubs with instrumentation stubs for 2nd client.
796 CheckConfigureStubs(kClientTwoKey,
797 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
798 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
799
800 // 1st client requests instrumentation deactivation but 2nd client still needs
801 // instrumentation stubs.
802 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
803 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
804 1U);
805
806 // 2nd client requests instrumentation deactivation
807 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
808 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
809}
810
811} // namespace instrumentation
812} // namespace art