blob: 56e3bc5745466e60d46320f6967c72253725928e [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 Geoffray81f0f952016-01-20 16:25:19 +000040 received_exception_caught_event(false), received_branch_event(false),
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010041 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
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000103 void Branch(Thread* thread ATTRIBUTE_UNUSED,
104 ArtMethod* method ATTRIBUTE_UNUSED,
105 uint32_t dex_pc ATTRIBUTE_UNUSED,
106 int32_t dex_pc_offset ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -0700107 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000108 received_branch_event = true;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200109 }
110
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100111 void InvokeVirtualOrInterface(Thread* thread ATTRIBUTE_UNUSED,
112 mirror::Object* this_object ATTRIBUTE_UNUSED,
113 ArtMethod* caller ATTRIBUTE_UNUSED,
114 uint32_t dex_pc ATTRIBUTE_UNUSED,
115 ArtMethod* callee ATTRIBUTE_UNUSED)
116 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
117 received_invoke_virtual_or_interface_event = true;
118 }
119
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200120 void Reset() {
121 received_method_enter_event = false;
122 received_method_exit_event = false;
123 received_method_unwind_event = false;
124 received_dex_pc_moved_event = false;
125 received_field_read_event = false;
126 received_field_written_event = false;
127 received_exception_caught_event = false;
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000128 received_branch_event = false;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100129 received_invoke_virtual_or_interface_event = false;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200130 }
131
132 bool received_method_enter_event;
133 bool received_method_exit_event;
134 bool received_method_unwind_event;
135 bool received_dex_pc_moved_event;
136 bool received_field_read_event;
137 bool received_field_written_event;
138 bool received_exception_caught_event;
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000139 bool received_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100140 bool received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200141
142 private:
143 DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
144};
145
146class InstrumentationTest : public CommonRuntimeTest {
147 public:
148 // Unique keys used to test Instrumentation::ConfigureStubs.
149 static constexpr const char* kClientOneKey = "TestClient1";
150 static constexpr const char* kClientTwoKey = "TestClient2";
151
152 void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
153 ScopedObjectAccess soa(Thread::Current());
154 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700155 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700156 gc::ScopedGCCriticalSection gcs(soa.Self(),
157 gc::kGcCauseInstrumentation,
158 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700159 ScopedSuspendAll ssa("Instrumentation::ConfigureStubs");
160 instr->ConfigureStubs(key, level);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200161 }
162
163 Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
164 return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
165 }
166
167 size_t GetInstrumentationUserCount() {
168 ScopedObjectAccess soa(Thread::Current());
169 return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
170 }
171
172 void TestEvent(uint32_t instrumentation_event) {
173 ScopedObjectAccess soa(Thread::Current());
174 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
175 TestInstrumentationListener listener;
176 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700177 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700178 ScopedSuspendAll ssa("Add instrumentation listener");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200179 instr->AddListener(&listener, instrumentation_event);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200180 }
181
Mathieu Chartiere401d142015-04-22 13:56:20 -0700182 ArtMethod* const event_method = nullptr;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200183 mirror::Object* const event_obj = nullptr;
184 const uint32_t event_dex_pc = 0;
185
186 // Check the listener is registered and is notified of the event.
187 EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
188 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
189 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
190 EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
191
192 listener.Reset();
193 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700194 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700195 ScopedSuspendAll ssa("Remove instrumentation listener");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200196 instr->RemoveListener(&listener, instrumentation_event);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200197 }
198
199 // Check the listener is not registered and is not notified of the event.
200 EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
201 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
202 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
203 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
204 }
205
Mathieu Chartiere401d142015-04-22 13:56:20 -0700206 void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700207 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200208 Runtime* runtime = Runtime::Current();
209 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700210 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700211 gc::ScopedGCCriticalSection gcs(self,
212 gc::kGcCauseInstrumentation,
213 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700214 ScopedSuspendAll ssa("Single method deoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200215 if (enable_deoptimization) {
216 instrumentation->EnableDeoptimization();
217 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700218 instrumentation->Deoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200219 }
220
Mathieu Chartiere401d142015-04-22 13:56:20 -0700221 void UndeoptimizeMethod(Thread* self, ArtMethod* method,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200222 const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700223 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200224 Runtime* runtime = Runtime::Current();
225 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700226 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700227 gc::ScopedGCCriticalSection gcs(self,
228 gc::kGcCauseInstrumentation,
229 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700230 ScopedSuspendAll ssa("Single method undeoptimization");
Mathieu Chartiere401d142015-04-22 13:56:20 -0700231 instrumentation->Undeoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200232 if (disable_deoptimization) {
233 instrumentation->DisableDeoptimization(key);
234 }
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200235 }
236
237 void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700238 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200239 Runtime* runtime = Runtime::Current();
240 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700241 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700242 gc::ScopedGCCriticalSection gcs(self,
243 gc::kGcCauseInstrumentation,
244 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700245 ScopedSuspendAll ssa("Full deoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200246 if (enable_deoptimization) {
247 instrumentation->EnableDeoptimization();
248 }
249 instrumentation->DeoptimizeEverything(key);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200250 }
251
252 void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700253 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200254 Runtime* runtime = Runtime::Current();
255 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700256 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700257 gc::ScopedGCCriticalSection gcs(self,
258 gc::kGcCauseInstrumentation,
259 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700260 ScopedSuspendAll ssa("Full undeoptimization");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200261 instrumentation->UndeoptimizeEverything(key);
262 if (disable_deoptimization) {
263 instrumentation->DisableDeoptimization(key);
264 }
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200265 }
266
267 void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
Mathieu Chartier90443472015-07-16 20:32:27 -0700268 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200269 Runtime* runtime = Runtime::Current();
270 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700271 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700272 gc::ScopedGCCriticalSection gcs(self,
273 gc::kGcCauseInstrumentation,
274 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700275 ScopedSuspendAll ssa("EnableMethodTracing");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200276 instrumentation->EnableMethodTracing(key, needs_interpreter);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200277 }
278
279 void DisableMethodTracing(Thread* self, const char* key)
Mathieu Chartier90443472015-07-16 20:32:27 -0700280 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200281 Runtime* runtime = Runtime::Current();
282 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700283 ScopedThreadSuspension sts(self, kSuspended);
Mathieu Chartieraa516822015-10-02 15:53:37 -0700284 gc::ScopedGCCriticalSection gcs(self,
285 gc::kGcCauseInstrumentation,
286 gc::kCollectorTypeInstrumentation);
Mathieu Chartier4f55e222015-09-04 13:26:21 -0700287 ScopedSuspendAll ssa("EnableMethodTracing");
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200288 instrumentation->DisableMethodTracing(key);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200289 }
290
291 private:
292 static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
Mathieu Chartier90443472015-07-16 20:32:27 -0700293 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200294 switch (event_type) {
295 case instrumentation::Instrumentation::kMethodEntered:
296 return instr->HasMethodEntryListeners();
297 case instrumentation::Instrumentation::kMethodExited:
298 return instr->HasMethodExitListeners();
299 case instrumentation::Instrumentation::kMethodUnwind:
300 return instr->HasMethodUnwindListeners();
301 case instrumentation::Instrumentation::kDexPcMoved:
302 return instr->HasDexPcListeners();
303 case instrumentation::Instrumentation::kFieldRead:
304 return instr->HasFieldReadListeners();
305 case instrumentation::Instrumentation::kFieldWritten:
306 return instr->HasFieldWriteListeners();
307 case instrumentation::Instrumentation::kExceptionCaught:
308 return instr->HasExceptionCaughtListeners();
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000309 case instrumentation::Instrumentation::kBranch:
310 return instr->HasBranchListeners();
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100311 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
312 return instr->HasInvokeVirtualOrInterfaceListeners();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200313 default:
314 LOG(FATAL) << "Unknown instrumentation event " << event_type;
315 UNREACHABLE();
316 }
317 }
318
319 static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700320 Thread* self, ArtMethod* method, mirror::Object* obj,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200321 uint32_t dex_pc)
Mathieu Chartier90443472015-07-16 20:32:27 -0700322 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200323 switch (event_type) {
324 case instrumentation::Instrumentation::kMethodEntered:
325 instr->MethodEnterEvent(self, obj, method, dex_pc);
326 break;
327 case instrumentation::Instrumentation::kMethodExited: {
328 JValue value;
329 instr->MethodExitEvent(self, obj, method, dex_pc, value);
330 break;
331 }
332 case instrumentation::Instrumentation::kMethodUnwind:
333 instr->MethodUnwindEvent(self, obj, method, dex_pc);
334 break;
335 case instrumentation::Instrumentation::kDexPcMoved:
336 instr->DexPcMovedEvent(self, obj, method, dex_pc);
337 break;
338 case instrumentation::Instrumentation::kFieldRead:
339 instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
340 break;
341 case instrumentation::Instrumentation::kFieldWritten: {
342 JValue value;
343 instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
344 break;
345 }
346 case instrumentation::Instrumentation::kExceptionCaught: {
347 ThrowArithmeticExceptionDivideByZero();
348 mirror::Throwable* event_exception = self->GetException();
349 instr->ExceptionCaughtEvent(self, event_exception);
350 self->ClearException();
351 break;
352 }
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000353 case instrumentation::Instrumentation::kBranch:
354 instr->Branch(self, method, dex_pc, -1);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200355 break;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100356 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
357 instr->InvokeVirtualOrInterface(self, obj, method, dex_pc, method);
358 break;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200359 default:
360 LOG(FATAL) << "Unknown instrumentation event " << event_type;
361 UNREACHABLE();
362 }
363 }
364
365 static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
366 uint32_t event_type) {
367 switch (event_type) {
368 case instrumentation::Instrumentation::kMethodEntered:
369 return listener.received_method_enter_event;
370 case instrumentation::Instrumentation::kMethodExited:
371 return listener.received_method_exit_event;
372 case instrumentation::Instrumentation::kMethodUnwind:
373 return listener.received_method_unwind_event;
374 case instrumentation::Instrumentation::kDexPcMoved:
375 return listener.received_dex_pc_moved_event;
376 case instrumentation::Instrumentation::kFieldRead:
377 return listener.received_field_read_event;
378 case instrumentation::Instrumentation::kFieldWritten:
379 return listener.received_field_written_event;
380 case instrumentation::Instrumentation::kExceptionCaught:
381 return listener.received_exception_caught_event;
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000382 case instrumentation::Instrumentation::kBranch:
383 return listener.received_branch_event;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100384 case instrumentation::Instrumentation::kInvokeVirtualOrInterface:
385 return listener.received_invoke_virtual_or_interface_event;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200386 default:
387 LOG(FATAL) << "Unknown instrumentation event " << event_type;
388 UNREACHABLE();
389 }
390 }
391};
392
393TEST_F(InstrumentationTest, NoInstrumentation) {
394 ScopedObjectAccess soa(Thread::Current());
395 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
396 ASSERT_NE(instr, nullptr);
397
398 EXPECT_FALSE(instr->AreExitStubsInstalled());
399 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
400 EXPECT_FALSE(instr->IsActive());
401 EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
402
403 // Test interpreter table is the default one.
404 EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
405
406 // Check there is no registered listener.
407 EXPECT_FALSE(instr->HasDexPcListeners());
408 EXPECT_FALSE(instr->HasExceptionCaughtListeners());
409 EXPECT_FALSE(instr->HasFieldReadListeners());
410 EXPECT_FALSE(instr->HasFieldWriteListeners());
411 EXPECT_FALSE(instr->HasMethodEntryListeners());
412 EXPECT_FALSE(instr->HasMethodExitListeners());
413 EXPECT_FALSE(instr->IsActive());
414}
415
416// Test instrumentation listeners for each event.
417TEST_F(InstrumentationTest, MethodEntryEvent) {
418 TestEvent(instrumentation::Instrumentation::kMethodEntered);
419}
420
421TEST_F(InstrumentationTest, MethodExitEvent) {
422 TestEvent(instrumentation::Instrumentation::kMethodExited);
423}
424
425TEST_F(InstrumentationTest, MethodUnwindEvent) {
426 TestEvent(instrumentation::Instrumentation::kMethodUnwind);
427}
428
429TEST_F(InstrumentationTest, DexPcMovedEvent) {
430 TestEvent(instrumentation::Instrumentation::kDexPcMoved);
431}
432
433TEST_F(InstrumentationTest, FieldReadEvent) {
434 TestEvent(instrumentation::Instrumentation::kFieldRead);
435}
436
437TEST_F(InstrumentationTest, FieldWriteEvent) {
438 TestEvent(instrumentation::Instrumentation::kFieldWritten);
439}
440
441TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
442 TestEvent(instrumentation::Instrumentation::kExceptionCaught);
443}
444
Nicolas Geoffray81f0f952016-01-20 16:25:19 +0000445TEST_F(InstrumentationTest, BranchEvent) {
446 TestEvent(instrumentation::Instrumentation::kBranch);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200447}
448
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100449TEST_F(InstrumentationTest, InvokeVirtualOrInterfaceEvent) {
450 TestEvent(instrumentation::Instrumentation::kInvokeVirtualOrInterface);
451}
452
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200453TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
454 ScopedObjectAccess soa(Thread::Current());
455 jobject class_loader = LoadDex("Instrumentation");
456 Runtime* const runtime = Runtime::Current();
457 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
458 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700459 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200460 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
461 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
462 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700463 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
464 sizeof(void*));
465 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200466
467 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700468 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200469
470 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
471
472 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
473 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700474 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200475
476 constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
477 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
478
479 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700480 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200481}
482
483TEST_F(InstrumentationTest, FullDeoptimization) {
484 ScopedObjectAccess soa(Thread::Current());
485 Runtime* const runtime = Runtime::Current();
486 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
487 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
488
489 constexpr const char* instrumentation_key = "FullDeoptimization";
490 DeoptimizeEverything(soa.Self(), instrumentation_key, true);
491
492 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
493 EXPECT_TRUE(instr->AreExitStubsInstalled());
494
495 UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
496
497 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
498}
499
500TEST_F(InstrumentationTest, MixedDeoptimization) {
501 ScopedObjectAccess soa(Thread::Current());
502 jobject class_loader = LoadDex("Instrumentation");
503 Runtime* const runtime = Runtime::Current();
504 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
505 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700506 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200507 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
508 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
509 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700510 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
511 sizeof(void*));
512 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200513
514 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700515 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200516
517 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
518 // Deoptimizing a method does not change instrumentation level.
519 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
520 GetCurrentInstrumentationLevel());
521 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
522 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700523 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200524
525 constexpr const char* instrumentation_key = "MixedDeoptimization";
526 DeoptimizeEverything(soa.Self(), instrumentation_key, false);
527 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
528 GetCurrentInstrumentationLevel());
529 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
530 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700531 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200532
533 UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
534 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
535 GetCurrentInstrumentationLevel());
536 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
537 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700538 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200539
540 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
541 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
542 GetCurrentInstrumentationLevel());
543 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700544 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200545}
546
547TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
548 ScopedObjectAccess soa(Thread::Current());
549 Runtime* const runtime = Runtime::Current();
550 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
551 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
552
553 constexpr const char* instrumentation_key = "MethodTracing";
554 EnableMethodTracing(soa.Self(), instrumentation_key, true);
555 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
556 GetCurrentInstrumentationLevel());
557 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
558 EXPECT_TRUE(instr->AreExitStubsInstalled());
559
560 DisableMethodTracing(soa.Self(), instrumentation_key);
561 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
562 GetCurrentInstrumentationLevel());
563 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
564}
565
566TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
567 ScopedObjectAccess soa(Thread::Current());
568 Runtime* const runtime = Runtime::Current();
569 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
570 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
571
572 constexpr const char* instrumentation_key = "MethodTracing";
573 EnableMethodTracing(soa.Self(), instrumentation_key, false);
574 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
575 GetCurrentInstrumentationLevel());
576 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
577 EXPECT_TRUE(instr->AreExitStubsInstalled());
578
579 DisableMethodTracing(soa.Self(), instrumentation_key);
580 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
581 GetCurrentInstrumentationLevel());
582 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
583}
584
585// We use a macro to print the line number where the test is failing.
586#define CHECK_INSTRUMENTATION(_level, _user_count) \
587 do { \
588 Instrumentation* const instr = Runtime::Current()->GetInstrumentation(); \
589 bool interpreter = \
590 (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); \
591 EXPECT_EQ(_level, GetCurrentInstrumentationLevel()); \
592 EXPECT_EQ(_user_count, GetInstrumentationUserCount()); \
593 if (instr->IsForcedInterpretOnly()) { \
594 EXPECT_TRUE(instr->InterpretOnly()); \
595 } else if (interpreter) { \
596 EXPECT_TRUE(instr->InterpretOnly()); \
597 } else { \
598 EXPECT_FALSE(instr->InterpretOnly()); \
599 } \
600 if (interpreter) { \
601 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); \
602 } else { \
603 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); \
604 } \
605 } while (false)
606
607TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
608 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
609
610 // Check no-op.
611 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
612 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
613}
614
615TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
616 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
617
618 // Check we can switch to instrumentation stubs
619 CheckConfigureStubs(kClientOneKey,
620 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
621 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
622 1U);
623
624 // Check we can disable instrumentation.
625 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
626 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
627}
628
629TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
630 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
631
632 // Check we can switch to interpreter
633 CheckConfigureStubs(kClientOneKey,
634 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
635 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
636
637 // Check we can disable instrumentation.
638 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
639 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
640}
641
642TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
643 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
644
645 // Configure stubs with instrumentation stubs.
646 CheckConfigureStubs(kClientOneKey,
647 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
648 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
649 1U);
650
651 // Configure stubs with interpreter.
652 CheckConfigureStubs(kClientOneKey,
653 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
654 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
655
656 // Check we can disable instrumentation.
657 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
658 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
659}
660
661TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
662 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
663
664 // Configure stubs with interpreter.
665 CheckConfigureStubs(kClientOneKey,
666 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
667 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
668
669 // Configure stubs with instrumentation stubs.
670 CheckConfigureStubs(kClientOneKey,
671 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
672 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
673 1U);
674
675 // Check we can disable instrumentation.
676 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
677 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
678}
679
680TEST_F(InstrumentationTest,
681 ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
682 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
683
684 // Configure stubs with instrumentation stubs.
685 CheckConfigureStubs(kClientOneKey,
686 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
687 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
688 1U);
689
690 // Configure stubs with interpreter.
691 CheckConfigureStubs(kClientOneKey,
692 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
693 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
694
695 // Configure stubs with instrumentation stubs again.
696 CheckConfigureStubs(kClientOneKey,
697 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
698 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
699 1U);
700
701 // Check we can disable instrumentation.
702 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
703 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
704}
705
706TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
707 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
708
709 // Check kInstrumentNothing with two clients.
710 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
711 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
712
713 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
714 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
715}
716
717TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
718 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
719
720 // Configure stubs with instrumentation stubs for 1st client.
721 CheckConfigureStubs(kClientOneKey,
722 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
723 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
724 1U);
725
726 // Configure stubs with instrumentation stubs for 2nd client.
727 CheckConfigureStubs(kClientTwoKey,
728 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
729 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
730 2U);
731
732 // 1st client requests instrumentation deactivation but 2nd client still needs
733 // instrumentation stubs.
734 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
735 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
736 1U);
737
738 // 2nd client requests instrumentation deactivation
739 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
740 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
741}
742
743TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
744 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
745
746 // Configure stubs with interpreter for 1st client.
747 CheckConfigureStubs(kClientOneKey,
748 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
749 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
750
751 // Configure stubs with interpreter for 2nd client.
752 CheckConfigureStubs(kClientTwoKey,
753 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
754 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
755
756 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
757 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
758 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
759
760 // 2nd client requests instrumentation deactivation
761 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
762 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
763}
764
765TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
766 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
767
768 // Configure stubs with instrumentation stubs for 1st client.
769 CheckConfigureStubs(kClientOneKey,
770 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
771 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
772 1U);
773
774 // Configure stubs with interpreter for 2nd client.
775 CheckConfigureStubs(kClientTwoKey,
776 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
777 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
778
779 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
780 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
781 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
782
783 // 2nd client requests instrumentation deactivation
784 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
785 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
786}
787
788TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
789 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
790
791 // Configure stubs with interpreter for 1st client.
792 CheckConfigureStubs(kClientOneKey,
793 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
794 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
795
796 // Configure stubs with instrumentation stubs for 2nd client.
797 CheckConfigureStubs(kClientTwoKey,
798 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
799 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
800
801 // 1st client requests instrumentation deactivation but 2nd client still needs
802 // instrumentation stubs.
803 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
804 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
805 1U);
806
807 // 2nd client requests instrumentation deactivation
808 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
809 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
810}
811
812} // namespace instrumentation
813} // namespace art