blob: 56fe9ef8ae05d87d3dd24834261fec15d4700f7d [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),
39 received_exception_caught_event(false), received_backward_branch_event(false) {}
40
41 virtual ~TestInstrumentationListener() {}
42
43 void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
44 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070045 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020046 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070047 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020048 received_method_enter_event = true;
49 }
50
51 void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
52 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070053 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020054 uint32_t dex_pc ATTRIBUTE_UNUSED,
55 const JValue& return_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070056 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020057 received_method_exit_event = true;
58 }
59
60 void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
61 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070062 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020063 uint32_t dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070064 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020065 received_method_unwind_event = true;
66 }
67
68 void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
69 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070070 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020071 uint32_t new_dex_pc ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070072 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020073 received_dex_pc_moved_event = true;
74 }
75
76 void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
77 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070078 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020079 uint32_t dex_pc ATTRIBUTE_UNUSED,
80 ArtField* field ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070081 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020082 received_field_read_event = true;
83 }
84
85 void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
86 mirror::Object* this_object ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -070087 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020088 uint32_t dex_pc ATTRIBUTE_UNUSED,
89 ArtField* field ATTRIBUTE_UNUSED,
90 const JValue& field_value ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070091 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020092 received_field_written_event = true;
93 }
94
95 void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
96 mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -070097 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +020098 received_exception_caught_event = true;
99 }
100
101 void BackwardBranch(Thread* thread ATTRIBUTE_UNUSED,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700102 ArtMethod* method ATTRIBUTE_UNUSED,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200103 int32_t dex_pc_offset ATTRIBUTE_UNUSED)
Mathieu Chartier90443472015-07-16 20:32:27 -0700104 OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200105 received_backward_branch_event = true;
106 }
107
108 void Reset() {
109 received_method_enter_event = false;
110 received_method_exit_event = false;
111 received_method_unwind_event = false;
112 received_dex_pc_moved_event = false;
113 received_field_read_event = false;
114 received_field_written_event = false;
115 received_exception_caught_event = false;
116 received_backward_branch_event = false;
117 }
118
119 bool received_method_enter_event;
120 bool received_method_exit_event;
121 bool received_method_unwind_event;
122 bool received_dex_pc_moved_event;
123 bool received_field_read_event;
124 bool received_field_written_event;
125 bool received_exception_caught_event;
126 bool received_backward_branch_event;
127
128 private:
129 DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
130};
131
132class InstrumentationTest : public CommonRuntimeTest {
133 public:
134 // Unique keys used to test Instrumentation::ConfigureStubs.
135 static constexpr const char* kClientOneKey = "TestClient1";
136 static constexpr const char* kClientTwoKey = "TestClient2";
137
138 void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
139 ScopedObjectAccess soa(Thread::Current());
140 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
141 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700142 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200143 Runtime* runtime = Runtime::Current();
144 runtime->GetThreadList()->SuspendAll("Instrumentation::ConfigureStubs");
145 instr->ConfigureStubs(key, level);
146 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200147 }
148 }
149
150 Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
151 return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
152 }
153
154 size_t GetInstrumentationUserCount() {
155 ScopedObjectAccess soa(Thread::Current());
156 return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
157 }
158
159 void TestEvent(uint32_t instrumentation_event) {
160 ScopedObjectAccess soa(Thread::Current());
161 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
162 TestInstrumentationListener listener;
163 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700164 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200165 Runtime* runtime = Runtime::Current();
166 runtime->GetThreadList()->SuspendAll("Add instrumentation listener");
167 instr->AddListener(&listener, instrumentation_event);
168 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200169 }
170
Mathieu Chartiere401d142015-04-22 13:56:20 -0700171 ArtMethod* const event_method = nullptr;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200172 mirror::Object* const event_obj = nullptr;
173 const uint32_t event_dex_pc = 0;
174
175 // Check the listener is registered and is notified of the event.
176 EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
177 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
178 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
179 EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
180
181 listener.Reset();
182 {
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700183 ScopedThreadSuspension sts(soa.Self(), kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200184 Runtime* runtime = Runtime::Current();
185 runtime->GetThreadList()->SuspendAll("Remove instrumentation listener");
186 instr->RemoveListener(&listener, instrumentation_event);
187 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200188 }
189
190 // Check the listener is not registered and is not notified of the event.
191 EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
192 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
193 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
194 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
195 }
196
Mathieu Chartiere401d142015-04-22 13:56:20 -0700197 void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700198 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200199 Runtime* runtime = Runtime::Current();
200 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700201 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200202 runtime->GetThreadList()->SuspendAll("Single method deoptimization");
203 if (enable_deoptimization) {
204 instrumentation->EnableDeoptimization();
205 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700206 instrumentation->Deoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200207 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200208 }
209
Mathieu Chartiere401d142015-04-22 13:56:20 -0700210 void UndeoptimizeMethod(Thread* self, ArtMethod* method,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200211 const char* key, bool disable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700212 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200213 Runtime* runtime = Runtime::Current();
214 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700215 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200216 runtime->GetThreadList()->SuspendAll("Single method undeoptimization");
Mathieu Chartiere401d142015-04-22 13:56:20 -0700217 instrumentation->Undeoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200218 if (disable_deoptimization) {
219 instrumentation->DisableDeoptimization(key);
220 }
221 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200222 }
223
224 void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
Mathieu Chartier90443472015-07-16 20:32:27 -0700225 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200226 Runtime* runtime = Runtime::Current();
227 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700228 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200229 runtime->GetThreadList()->SuspendAll("Full deoptimization");
230 if (enable_deoptimization) {
231 instrumentation->EnableDeoptimization();
232 }
233 instrumentation->DeoptimizeEverything(key);
234 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200235 }
236
237 void UndeoptimizeEverything(Thread* self, const char* key, bool disable_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);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200242 runtime->GetThreadList()->SuspendAll("Full undeoptimization");
243 instrumentation->UndeoptimizeEverything(key);
244 if (disable_deoptimization) {
245 instrumentation->DisableDeoptimization(key);
246 }
247 runtime->GetThreadList()->ResumeAll();
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);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200255 runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
256 instrumentation->EnableMethodTracing(key, needs_interpreter);
257 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200258 }
259
260 void DisableMethodTracing(Thread* self, const char* key)
Mathieu Chartier90443472015-07-16 20:32:27 -0700261 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200262 Runtime* runtime = Runtime::Current();
263 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700264 ScopedThreadSuspension sts(self, kSuspended);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200265 runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
266 instrumentation->DisableMethodTracing(key);
267 runtime->GetThreadList()->ResumeAll();
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200268 }
269
270 private:
271 static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
Mathieu Chartier90443472015-07-16 20:32:27 -0700272 SHARED_REQUIRES(Locks::mutator_lock_) {
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200273 switch (event_type) {
274 case instrumentation::Instrumentation::kMethodEntered:
275 return instr->HasMethodEntryListeners();
276 case instrumentation::Instrumentation::kMethodExited:
277 return instr->HasMethodExitListeners();
278 case instrumentation::Instrumentation::kMethodUnwind:
279 return instr->HasMethodUnwindListeners();
280 case instrumentation::Instrumentation::kDexPcMoved:
281 return instr->HasDexPcListeners();
282 case instrumentation::Instrumentation::kFieldRead:
283 return instr->HasFieldReadListeners();
284 case instrumentation::Instrumentation::kFieldWritten:
285 return instr->HasFieldWriteListeners();
286 case instrumentation::Instrumentation::kExceptionCaught:
287 return instr->HasExceptionCaughtListeners();
288 case instrumentation::Instrumentation::kBackwardBranch:
289 return instr->HasBackwardBranchListeners();
290 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;
333 default:
334 LOG(FATAL) << "Unknown instrumentation event " << event_type;
335 UNREACHABLE();
336 }
337 }
338
339 static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
340 uint32_t event_type) {
341 switch (event_type) {
342 case instrumentation::Instrumentation::kMethodEntered:
343 return listener.received_method_enter_event;
344 case instrumentation::Instrumentation::kMethodExited:
345 return listener.received_method_exit_event;
346 case instrumentation::Instrumentation::kMethodUnwind:
347 return listener.received_method_unwind_event;
348 case instrumentation::Instrumentation::kDexPcMoved:
349 return listener.received_dex_pc_moved_event;
350 case instrumentation::Instrumentation::kFieldRead:
351 return listener.received_field_read_event;
352 case instrumentation::Instrumentation::kFieldWritten:
353 return listener.received_field_written_event;
354 case instrumentation::Instrumentation::kExceptionCaught:
355 return listener.received_exception_caught_event;
356 case instrumentation::Instrumentation::kBackwardBranch:
357 return listener.received_backward_branch_event;
358 default:
359 LOG(FATAL) << "Unknown instrumentation event " << event_type;
360 UNREACHABLE();
361 }
362 }
363};
364
365TEST_F(InstrumentationTest, NoInstrumentation) {
366 ScopedObjectAccess soa(Thread::Current());
367 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
368 ASSERT_NE(instr, nullptr);
369
370 EXPECT_FALSE(instr->AreExitStubsInstalled());
371 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
372 EXPECT_FALSE(instr->IsActive());
373 EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
374
375 // Test interpreter table is the default one.
376 EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
377
378 // Check there is no registered listener.
379 EXPECT_FALSE(instr->HasDexPcListeners());
380 EXPECT_FALSE(instr->HasExceptionCaughtListeners());
381 EXPECT_FALSE(instr->HasFieldReadListeners());
382 EXPECT_FALSE(instr->HasFieldWriteListeners());
383 EXPECT_FALSE(instr->HasMethodEntryListeners());
384 EXPECT_FALSE(instr->HasMethodExitListeners());
385 EXPECT_FALSE(instr->IsActive());
386}
387
388// Test instrumentation listeners for each event.
389TEST_F(InstrumentationTest, MethodEntryEvent) {
390 TestEvent(instrumentation::Instrumentation::kMethodEntered);
391}
392
393TEST_F(InstrumentationTest, MethodExitEvent) {
394 TestEvent(instrumentation::Instrumentation::kMethodExited);
395}
396
397TEST_F(InstrumentationTest, MethodUnwindEvent) {
398 TestEvent(instrumentation::Instrumentation::kMethodUnwind);
399}
400
401TEST_F(InstrumentationTest, DexPcMovedEvent) {
402 TestEvent(instrumentation::Instrumentation::kDexPcMoved);
403}
404
405TEST_F(InstrumentationTest, FieldReadEvent) {
406 TestEvent(instrumentation::Instrumentation::kFieldRead);
407}
408
409TEST_F(InstrumentationTest, FieldWriteEvent) {
410 TestEvent(instrumentation::Instrumentation::kFieldWritten);
411}
412
413TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
414 TestEvent(instrumentation::Instrumentation::kExceptionCaught);
415}
416
417TEST_F(InstrumentationTest, BackwardBranchEvent) {
418 TestEvent(instrumentation::Instrumentation::kBackwardBranch);
419}
420
421TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
422 ScopedObjectAccess soa(Thread::Current());
423 jobject class_loader = LoadDex("Instrumentation");
424 Runtime* const runtime = Runtime::Current();
425 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
426 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700427 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200428 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
429 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
430 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700431 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
432 sizeof(void*));
433 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200434
435 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700436 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200437
438 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
439
440 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
441 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700442 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200443
444 constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
445 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
446
447 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700448 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200449}
450
451TEST_F(InstrumentationTest, FullDeoptimization) {
452 ScopedObjectAccess soa(Thread::Current());
453 Runtime* const runtime = Runtime::Current();
454 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
455 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
456
457 constexpr const char* instrumentation_key = "FullDeoptimization";
458 DeoptimizeEverything(soa.Self(), instrumentation_key, true);
459
460 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
461 EXPECT_TRUE(instr->AreExitStubsInstalled());
462
463 UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
464
465 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
466}
467
468TEST_F(InstrumentationTest, MixedDeoptimization) {
469 ScopedObjectAccess soa(Thread::Current());
470 jobject class_loader = LoadDex("Instrumentation");
471 Runtime* const runtime = Runtime::Current();
472 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
473 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700474 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200475 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
476 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
477 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700478 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
479 sizeof(void*));
480 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200481
482 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700483 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200484
485 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
486 // Deoptimizing a method does not change instrumentation level.
487 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
488 GetCurrentInstrumentationLevel());
489 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
490 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700491 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200492
493 constexpr const char* instrumentation_key = "MixedDeoptimization";
494 DeoptimizeEverything(soa.Self(), instrumentation_key, false);
495 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
496 GetCurrentInstrumentationLevel());
497 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
498 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700499 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200500
501 UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
502 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
503 GetCurrentInstrumentationLevel());
504 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
505 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700506 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200507
508 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
509 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
510 GetCurrentInstrumentationLevel());
511 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700512 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200513}
514
515TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
516 ScopedObjectAccess soa(Thread::Current());
517 Runtime* const runtime = Runtime::Current();
518 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
519 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
520
521 constexpr const char* instrumentation_key = "MethodTracing";
522 EnableMethodTracing(soa.Self(), instrumentation_key, true);
523 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
524 GetCurrentInstrumentationLevel());
525 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
526 EXPECT_TRUE(instr->AreExitStubsInstalled());
527
528 DisableMethodTracing(soa.Self(), instrumentation_key);
529 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
530 GetCurrentInstrumentationLevel());
531 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
532}
533
534TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
535 ScopedObjectAccess soa(Thread::Current());
536 Runtime* const runtime = Runtime::Current();
537 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
538 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
539
540 constexpr const char* instrumentation_key = "MethodTracing";
541 EnableMethodTracing(soa.Self(), instrumentation_key, false);
542 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
543 GetCurrentInstrumentationLevel());
544 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
545 EXPECT_TRUE(instr->AreExitStubsInstalled());
546
547 DisableMethodTracing(soa.Self(), instrumentation_key);
548 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
549 GetCurrentInstrumentationLevel());
550 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
551}
552
553// We use a macro to print the line number where the test is failing.
554#define CHECK_INSTRUMENTATION(_level, _user_count) \
555 do { \
556 Instrumentation* const instr = Runtime::Current()->GetInstrumentation(); \
557 bool interpreter = \
558 (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); \
559 EXPECT_EQ(_level, GetCurrentInstrumentationLevel()); \
560 EXPECT_EQ(_user_count, GetInstrumentationUserCount()); \
561 if (instr->IsForcedInterpretOnly()) { \
562 EXPECT_TRUE(instr->InterpretOnly()); \
563 } else if (interpreter) { \
564 EXPECT_TRUE(instr->InterpretOnly()); \
565 } else { \
566 EXPECT_FALSE(instr->InterpretOnly()); \
567 } \
568 if (interpreter) { \
569 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); \
570 } else { \
571 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); \
572 } \
573 } while (false)
574
575TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
576 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
577
578 // Check no-op.
579 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
580 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
581}
582
583TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
584 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
585
586 // Check we can switch to instrumentation stubs
587 CheckConfigureStubs(kClientOneKey,
588 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
589 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
590 1U);
591
592 // Check we can disable instrumentation.
593 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
594 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
595}
596
597TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
598 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
599
600 // Check we can switch to interpreter
601 CheckConfigureStubs(kClientOneKey,
602 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
603 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
604
605 // Check we can disable instrumentation.
606 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
607 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
608}
609
610TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
611 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
612
613 // Configure stubs with instrumentation stubs.
614 CheckConfigureStubs(kClientOneKey,
615 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
616 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
617 1U);
618
619 // Configure stubs with interpreter.
620 CheckConfigureStubs(kClientOneKey,
621 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
622 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 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_InterpreterToInstrumentationStubs) {
630 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
631
632 // Configure stubs with interpreter.
633 CheckConfigureStubs(kClientOneKey,
634 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
635 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
636
637 // Configure stubs with instrumentation stubs.
638 CheckConfigureStubs(kClientOneKey,
639 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
640 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
641 1U);
642
643 // Check we can disable instrumentation.
644 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
645 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
646}
647
648TEST_F(InstrumentationTest,
649 ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
650 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
651
652 // Configure stubs with instrumentation stubs.
653 CheckConfigureStubs(kClientOneKey,
654 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
655 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
656 1U);
657
658 // Configure stubs with interpreter.
659 CheckConfigureStubs(kClientOneKey,
660 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
661 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
662
663 // Configure stubs with instrumentation stubs again.
664 CheckConfigureStubs(kClientOneKey,
665 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
666 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
667 1U);
668
669 // Check we can disable instrumentation.
670 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
671 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
672}
673
674TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
675 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
676
677 // Check kInstrumentNothing with two clients.
678 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
679 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
680
681 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
682 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
683}
684
685TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
686 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
687
688 // Configure stubs with instrumentation stubs for 1st client.
689 CheckConfigureStubs(kClientOneKey,
690 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
691 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
692 1U);
693
694 // Configure stubs with instrumentation stubs for 2nd client.
695 CheckConfigureStubs(kClientTwoKey,
696 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
697 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
698 2U);
699
700 // 1st client requests instrumentation deactivation but 2nd client still needs
701 // instrumentation stubs.
702 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
703 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
704 1U);
705
706 // 2nd client requests instrumentation deactivation
707 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
708 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
709}
710
711TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
712 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
713
714 // Configure stubs with interpreter for 1st client.
715 CheckConfigureStubs(kClientOneKey,
716 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
717 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
718
719 // Configure stubs with interpreter for 2nd client.
720 CheckConfigureStubs(kClientTwoKey,
721 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
722 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
723
724 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
725 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
726 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
727
728 // 2nd client requests instrumentation deactivation
729 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
730 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
731}
732
733TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
734 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
735
736 // Configure stubs with instrumentation stubs for 1st client.
737 CheckConfigureStubs(kClientOneKey,
738 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
739 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
740 1U);
741
742 // Configure stubs with interpreter for 2nd client.
743 CheckConfigureStubs(kClientTwoKey,
744 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
745 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
746
747 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
748 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
749 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
750
751 // 2nd client requests instrumentation deactivation
752 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
753 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
754}
755
756TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
757 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
758
759 // Configure stubs with interpreter for 1st client.
760 CheckConfigureStubs(kClientOneKey,
761 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
762 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
763
764 // Configure stubs with instrumentation stubs for 2nd client.
765 CheckConfigureStubs(kClientTwoKey,
766 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
767 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
768
769 // 1st client requests instrumentation deactivation but 2nd client still needs
770 // instrumentation stubs.
771 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
772 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
773 1U);
774
775 // 2nd client requests instrumentation deactivation
776 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
777 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
778}
779
780} // namespace instrumentation
781} // namespace art