blob: 85bb8c4197612ac5dc705560156a54420f4d51ab [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)
47 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
48 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)
56 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
57 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)
64 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
65 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)
72 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
73 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)
81 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
82 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)
91 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
92 received_field_written_event = true;
93 }
94
95 void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
96 mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
97 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
98 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)
104 OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
105 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 {
142 soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
143 Runtime* runtime = Runtime::Current();
144 runtime->GetThreadList()->SuspendAll("Instrumentation::ConfigureStubs");
145 instr->ConfigureStubs(key, level);
146 runtime->GetThreadList()->ResumeAll();
147 soa.Self()->TransitionFromSuspendedToRunnable();
148 }
149 }
150
151 Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
152 return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
153 }
154
155 size_t GetInstrumentationUserCount() {
156 ScopedObjectAccess soa(Thread::Current());
157 return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
158 }
159
160 void TestEvent(uint32_t instrumentation_event) {
161 ScopedObjectAccess soa(Thread::Current());
162 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
163 TestInstrumentationListener listener;
164 {
165 soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
166 Runtime* runtime = Runtime::Current();
167 runtime->GetThreadList()->SuspendAll("Add instrumentation listener");
168 instr->AddListener(&listener, instrumentation_event);
169 runtime->GetThreadList()->ResumeAll();
170 soa.Self()->TransitionFromSuspendedToRunnable();
171 }
172
Mathieu Chartiere401d142015-04-22 13:56:20 -0700173 ArtMethod* const event_method = nullptr;
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200174 mirror::Object* const event_obj = nullptr;
175 const uint32_t event_dex_pc = 0;
176
177 // Check the listener is registered and is notified of the event.
178 EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
179 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
180 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
181 EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
182
183 listener.Reset();
184 {
185 soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
186 Runtime* runtime = Runtime::Current();
187 runtime->GetThreadList()->SuspendAll("Remove instrumentation listener");
188 instr->RemoveListener(&listener, instrumentation_event);
189 runtime->GetThreadList()->ResumeAll();
190 soa.Self()->TransitionFromSuspendedToRunnable();
191 }
192
193 // Check the listener is not registered and is not notified of the event.
194 EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
195 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
196 ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
197 EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
198 }
199
Mathieu Chartiere401d142015-04-22 13:56:20 -0700200 void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200201 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
202 Runtime* runtime = Runtime::Current();
203 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
204 self->TransitionFromRunnableToSuspended(kSuspended);
205 runtime->GetThreadList()->SuspendAll("Single method deoptimization");
206 if (enable_deoptimization) {
207 instrumentation->EnableDeoptimization();
208 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700209 instrumentation->Deoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200210 runtime->GetThreadList()->ResumeAll();
211 self->TransitionFromSuspendedToRunnable();
212 }
213
Mathieu Chartiere401d142015-04-22 13:56:20 -0700214 void UndeoptimizeMethod(Thread* self, ArtMethod* method,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200215 const char* key, bool disable_deoptimization)
216 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
217 Runtime* runtime = Runtime::Current();
218 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
219 self->TransitionFromRunnableToSuspended(kSuspended);
220 runtime->GetThreadList()->SuspendAll("Single method undeoptimization");
Mathieu Chartiere401d142015-04-22 13:56:20 -0700221 instrumentation->Undeoptimize(method);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200222 if (disable_deoptimization) {
223 instrumentation->DisableDeoptimization(key);
224 }
225 runtime->GetThreadList()->ResumeAll();
226 self->TransitionFromSuspendedToRunnable();
227 }
228
229 void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
230 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
231 Runtime* runtime = Runtime::Current();
232 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
233 self->TransitionFromRunnableToSuspended(kSuspended);
234 runtime->GetThreadList()->SuspendAll("Full deoptimization");
235 if (enable_deoptimization) {
236 instrumentation->EnableDeoptimization();
237 }
238 instrumentation->DeoptimizeEverything(key);
239 runtime->GetThreadList()->ResumeAll();
240 self->TransitionFromSuspendedToRunnable();
241 }
242
243 void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
244 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
245 Runtime* runtime = Runtime::Current();
246 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
247 self->TransitionFromRunnableToSuspended(kSuspended);
248 runtime->GetThreadList()->SuspendAll("Full undeoptimization");
249 instrumentation->UndeoptimizeEverything(key);
250 if (disable_deoptimization) {
251 instrumentation->DisableDeoptimization(key);
252 }
253 runtime->GetThreadList()->ResumeAll();
254 self->TransitionFromSuspendedToRunnable();
255 }
256
257 void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
258 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
259 Runtime* runtime = Runtime::Current();
260 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
261 self->TransitionFromRunnableToSuspended(kSuspended);
262 runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
263 instrumentation->EnableMethodTracing(key, needs_interpreter);
264 runtime->GetThreadList()->ResumeAll();
265 self->TransitionFromSuspendedToRunnable();
266 }
267
268 void DisableMethodTracing(Thread* self, const char* key)
269 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
270 Runtime* runtime = Runtime::Current();
271 instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
272 self->TransitionFromRunnableToSuspended(kSuspended);
273 runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
274 instrumentation->DisableMethodTracing(key);
275 runtime->GetThreadList()->ResumeAll();
276 self->TransitionFromSuspendedToRunnable();
277 }
278
279 private:
280 static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
281 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
282 switch (event_type) {
283 case instrumentation::Instrumentation::kMethodEntered:
284 return instr->HasMethodEntryListeners();
285 case instrumentation::Instrumentation::kMethodExited:
286 return instr->HasMethodExitListeners();
287 case instrumentation::Instrumentation::kMethodUnwind:
288 return instr->HasMethodUnwindListeners();
289 case instrumentation::Instrumentation::kDexPcMoved:
290 return instr->HasDexPcListeners();
291 case instrumentation::Instrumentation::kFieldRead:
292 return instr->HasFieldReadListeners();
293 case instrumentation::Instrumentation::kFieldWritten:
294 return instr->HasFieldWriteListeners();
295 case instrumentation::Instrumentation::kExceptionCaught:
296 return instr->HasExceptionCaughtListeners();
297 case instrumentation::Instrumentation::kBackwardBranch:
298 return instr->HasBackwardBranchListeners();
299 default:
300 LOG(FATAL) << "Unknown instrumentation event " << event_type;
301 UNREACHABLE();
302 }
303 }
304
305 static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700306 Thread* self, ArtMethod* method, mirror::Object* obj,
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200307 uint32_t dex_pc)
308 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
309 switch (event_type) {
310 case instrumentation::Instrumentation::kMethodEntered:
311 instr->MethodEnterEvent(self, obj, method, dex_pc);
312 break;
313 case instrumentation::Instrumentation::kMethodExited: {
314 JValue value;
315 instr->MethodExitEvent(self, obj, method, dex_pc, value);
316 break;
317 }
318 case instrumentation::Instrumentation::kMethodUnwind:
319 instr->MethodUnwindEvent(self, obj, method, dex_pc);
320 break;
321 case instrumentation::Instrumentation::kDexPcMoved:
322 instr->DexPcMovedEvent(self, obj, method, dex_pc);
323 break;
324 case instrumentation::Instrumentation::kFieldRead:
325 instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
326 break;
327 case instrumentation::Instrumentation::kFieldWritten: {
328 JValue value;
329 instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
330 break;
331 }
332 case instrumentation::Instrumentation::kExceptionCaught: {
333 ThrowArithmeticExceptionDivideByZero();
334 mirror::Throwable* event_exception = self->GetException();
335 instr->ExceptionCaughtEvent(self, event_exception);
336 self->ClearException();
337 break;
338 }
339 case instrumentation::Instrumentation::kBackwardBranch:
340 instr->BackwardBranch(self, method, dex_pc);
341 break;
342 default:
343 LOG(FATAL) << "Unknown instrumentation event " << event_type;
344 UNREACHABLE();
345 }
346 }
347
348 static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
349 uint32_t event_type) {
350 switch (event_type) {
351 case instrumentation::Instrumentation::kMethodEntered:
352 return listener.received_method_enter_event;
353 case instrumentation::Instrumentation::kMethodExited:
354 return listener.received_method_exit_event;
355 case instrumentation::Instrumentation::kMethodUnwind:
356 return listener.received_method_unwind_event;
357 case instrumentation::Instrumentation::kDexPcMoved:
358 return listener.received_dex_pc_moved_event;
359 case instrumentation::Instrumentation::kFieldRead:
360 return listener.received_field_read_event;
361 case instrumentation::Instrumentation::kFieldWritten:
362 return listener.received_field_written_event;
363 case instrumentation::Instrumentation::kExceptionCaught:
364 return listener.received_exception_caught_event;
365 case instrumentation::Instrumentation::kBackwardBranch:
366 return listener.received_backward_branch_event;
367 default:
368 LOG(FATAL) << "Unknown instrumentation event " << event_type;
369 UNREACHABLE();
370 }
371 }
372};
373
374TEST_F(InstrumentationTest, NoInstrumentation) {
375 ScopedObjectAccess soa(Thread::Current());
376 instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
377 ASSERT_NE(instr, nullptr);
378
379 EXPECT_FALSE(instr->AreExitStubsInstalled());
380 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
381 EXPECT_FALSE(instr->IsActive());
382 EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
383
384 // Test interpreter table is the default one.
385 EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
386
387 // Check there is no registered listener.
388 EXPECT_FALSE(instr->HasDexPcListeners());
389 EXPECT_FALSE(instr->HasExceptionCaughtListeners());
390 EXPECT_FALSE(instr->HasFieldReadListeners());
391 EXPECT_FALSE(instr->HasFieldWriteListeners());
392 EXPECT_FALSE(instr->HasMethodEntryListeners());
393 EXPECT_FALSE(instr->HasMethodExitListeners());
394 EXPECT_FALSE(instr->IsActive());
395}
396
397// Test instrumentation listeners for each event.
398TEST_F(InstrumentationTest, MethodEntryEvent) {
399 TestEvent(instrumentation::Instrumentation::kMethodEntered);
400}
401
402TEST_F(InstrumentationTest, MethodExitEvent) {
403 TestEvent(instrumentation::Instrumentation::kMethodExited);
404}
405
406TEST_F(InstrumentationTest, MethodUnwindEvent) {
407 TestEvent(instrumentation::Instrumentation::kMethodUnwind);
408}
409
410TEST_F(InstrumentationTest, DexPcMovedEvent) {
411 TestEvent(instrumentation::Instrumentation::kDexPcMoved);
412}
413
414TEST_F(InstrumentationTest, FieldReadEvent) {
415 TestEvent(instrumentation::Instrumentation::kFieldRead);
416}
417
418TEST_F(InstrumentationTest, FieldWriteEvent) {
419 TestEvent(instrumentation::Instrumentation::kFieldWritten);
420}
421
422TEST_F(InstrumentationTest, ExceptionCaughtEvent) {
423 TestEvent(instrumentation::Instrumentation::kExceptionCaught);
424}
425
426TEST_F(InstrumentationTest, BackwardBranchEvent) {
427 TestEvent(instrumentation::Instrumentation::kBackwardBranch);
428}
429
430TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
431 ScopedObjectAccess soa(Thread::Current());
432 jobject class_loader = LoadDex("Instrumentation");
433 Runtime* const runtime = Runtime::Current();
434 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
435 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700436 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200437 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
438 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
439 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700440 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
441 sizeof(void*));
442 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200443
444 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700445 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200446
447 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
448
449 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
450 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700451 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200452
453 constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
454 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
455
456 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700457 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200458}
459
460TEST_F(InstrumentationTest, FullDeoptimization) {
461 ScopedObjectAccess soa(Thread::Current());
462 Runtime* const runtime = Runtime::Current();
463 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
464 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
465
466 constexpr const char* instrumentation_key = "FullDeoptimization";
467 DeoptimizeEverything(soa.Self(), instrumentation_key, true);
468
469 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
470 EXPECT_TRUE(instr->AreExitStubsInstalled());
471
472 UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
473
474 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
475}
476
477TEST_F(InstrumentationTest, MixedDeoptimization) {
478 ScopedObjectAccess soa(Thread::Current());
479 jobject class_loader = LoadDex("Instrumentation");
480 Runtime* const runtime = Runtime::Current();
481 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
482 ClassLinker* class_linker = runtime->GetClassLinker();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700483 StackHandleScope<1> hs(soa.Self());
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200484 Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
485 mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
486 ASSERT_TRUE(klass != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700487 ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
488 sizeof(void*));
489 ASSERT_TRUE(method_to_deoptimize != nullptr);
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200490
491 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700492 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200493
494 DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
495 // Deoptimizing a method does not change instrumentation level.
496 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
497 GetCurrentInstrumentationLevel());
498 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
499 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700500 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200501
502 constexpr const char* instrumentation_key = "MixedDeoptimization";
503 DeoptimizeEverything(soa.Self(), instrumentation_key, false);
504 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
505 GetCurrentInstrumentationLevel());
506 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
507 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700508 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200509
510 UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
511 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
512 GetCurrentInstrumentationLevel());
513 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
514 EXPECT_TRUE(instr->AreExitStubsInstalled());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700515 EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200516
517 UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
518 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
519 GetCurrentInstrumentationLevel());
520 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700521 EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
Sebastien Hertz0462c4c2015-04-01 16:34:17 +0200522}
523
524TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
525 ScopedObjectAccess soa(Thread::Current());
526 Runtime* const runtime = Runtime::Current();
527 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
528 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
529
530 constexpr const char* instrumentation_key = "MethodTracing";
531 EnableMethodTracing(soa.Self(), instrumentation_key, true);
532 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
533 GetCurrentInstrumentationLevel());
534 EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
535 EXPECT_TRUE(instr->AreExitStubsInstalled());
536
537 DisableMethodTracing(soa.Self(), instrumentation_key);
538 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
539 GetCurrentInstrumentationLevel());
540 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
541}
542
543TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
544 ScopedObjectAccess soa(Thread::Current());
545 Runtime* const runtime = Runtime::Current();
546 instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
547 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
548
549 constexpr const char* instrumentation_key = "MethodTracing";
550 EnableMethodTracing(soa.Self(), instrumentation_key, false);
551 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
552 GetCurrentInstrumentationLevel());
553 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
554 EXPECT_TRUE(instr->AreExitStubsInstalled());
555
556 DisableMethodTracing(soa.Self(), instrumentation_key);
557 EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
558 GetCurrentInstrumentationLevel());
559 EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
560}
561
562// We use a macro to print the line number where the test is failing.
563#define CHECK_INSTRUMENTATION(_level, _user_count) \
564 do { \
565 Instrumentation* const instr = Runtime::Current()->GetInstrumentation(); \
566 bool interpreter = \
567 (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter); \
568 EXPECT_EQ(_level, GetCurrentInstrumentationLevel()); \
569 EXPECT_EQ(_user_count, GetInstrumentationUserCount()); \
570 if (instr->IsForcedInterpretOnly()) { \
571 EXPECT_TRUE(instr->InterpretOnly()); \
572 } else if (interpreter) { \
573 EXPECT_TRUE(instr->InterpretOnly()); \
574 } else { \
575 EXPECT_FALSE(instr->InterpretOnly()); \
576 } \
577 if (interpreter) { \
578 EXPECT_TRUE(instr->AreAllMethodsDeoptimized()); \
579 } else { \
580 EXPECT_FALSE(instr->AreAllMethodsDeoptimized()); \
581 } \
582 } while (false)
583
584TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
585 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
586
587 // Check no-op.
588 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
589 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
590}
591
592TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
593 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
594
595 // Check we can switch to instrumentation stubs
596 CheckConfigureStubs(kClientOneKey,
597 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
598 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
599 1U);
600
601 // Check we can disable instrumentation.
602 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
603 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
604}
605
606TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
607 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
608
609 // Check we can switch to interpreter
610 CheckConfigureStubs(kClientOneKey,
611 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
612 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
613
614 // Check we can disable instrumentation.
615 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
616 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
617}
618
619TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
620 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
621
622 // Configure stubs with instrumentation stubs.
623 CheckConfigureStubs(kClientOneKey,
624 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
625 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
626 1U);
627
628 // Configure stubs with interpreter.
629 CheckConfigureStubs(kClientOneKey,
630 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
631 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
632
633 // Check we can disable instrumentation.
634 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
635 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
636}
637
638TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
639 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
640
641 // Configure stubs with interpreter.
642 CheckConfigureStubs(kClientOneKey,
643 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
644 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
645
646 // Configure stubs with instrumentation stubs.
647 CheckConfigureStubs(kClientOneKey,
648 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
649 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
650 1U);
651
652 // Check we can disable instrumentation.
653 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
654 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
655}
656
657TEST_F(InstrumentationTest,
658 ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
659 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
660
661 // Configure stubs with instrumentation stubs.
662 CheckConfigureStubs(kClientOneKey,
663 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
664 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
665 1U);
666
667 // Configure stubs with interpreter.
668 CheckConfigureStubs(kClientOneKey,
669 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
670 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
671
672 // Configure stubs with instrumentation stubs again.
673 CheckConfigureStubs(kClientOneKey,
674 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
675 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
676 1U);
677
678 // Check we can disable instrumentation.
679 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
680 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
681}
682
683TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
684 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
685
686 // Check kInstrumentNothing with two clients.
687 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
688 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
689
690 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
691 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
692}
693
694TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
695 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
696
697 // Configure stubs with instrumentation stubs for 1st client.
698 CheckConfigureStubs(kClientOneKey,
699 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
700 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
701 1U);
702
703 // Configure stubs with instrumentation stubs for 2nd client.
704 CheckConfigureStubs(kClientTwoKey,
705 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
706 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
707 2U);
708
709 // 1st client requests instrumentation deactivation but 2nd client still needs
710 // instrumentation stubs.
711 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
712 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
713 1U);
714
715 // 2nd client requests instrumentation deactivation
716 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
717 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
718}
719
720TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
721 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
722
723 // Configure stubs with interpreter for 1st client.
724 CheckConfigureStubs(kClientOneKey,
725 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
726 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
727
728 // Configure stubs with interpreter for 2nd client.
729 CheckConfigureStubs(kClientTwoKey,
730 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
731 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
732
733 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
734 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
735 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
736
737 // 2nd client requests instrumentation deactivation
738 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
739 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
740}
741
742TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
743 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
744
745 // Configure stubs with instrumentation stubs for 1st client.
746 CheckConfigureStubs(kClientOneKey,
747 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
748 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
749 1U);
750
751 // Configure stubs with interpreter for 2nd client.
752 CheckConfigureStubs(kClientTwoKey,
753 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
754 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
755
756 // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
757 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
758 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
759
760 // 2nd client requests instrumentation deactivation
761 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
762 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
763}
764
765TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
766 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
767
768 // Configure stubs with interpreter for 1st client.
769 CheckConfigureStubs(kClientOneKey,
770 Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
771 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
772
773 // Configure stubs with instrumentation stubs for 2nd client.
774 CheckConfigureStubs(kClientTwoKey,
775 Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
776 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
777
778 // 1st client requests instrumentation deactivation but 2nd client still needs
779 // instrumentation stubs.
780 CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
781 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
782 1U);
783
784 // 2nd client requests instrumentation deactivation
785 CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
786 CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
787}
788
789} // namespace instrumentation
790} // namespace art