xref: /aosp_15_r20/art/runtime/instrumentation_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
20*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
22*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
23*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
24*795d594fSAndroid Build Coastguard Worker #include "common_throws.h"
25*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
26*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
27*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
29*795d594fSAndroid Build Coastguard Worker #include "jvalue.h"
30*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
31*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "interpreter/shadow_frame.h"
33*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
34*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
35*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
38*795d594fSAndroid Build Coastguard Worker namespace instrumentation {
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker class TestInstrumentationListener final : public instrumentation::InstrumentationListener {
41*795d594fSAndroid Build Coastguard Worker  public:
TestInstrumentationListener()42*795d594fSAndroid Build Coastguard Worker   TestInstrumentationListener()
43*795d594fSAndroid Build Coastguard Worker     : received_method_enter_event(false),
44*795d594fSAndroid Build Coastguard Worker       received_method_exit_event(false),
45*795d594fSAndroid Build Coastguard Worker       received_method_exit_object_event(false),
46*795d594fSAndroid Build Coastguard Worker       received_method_unwind_event(false),
47*795d594fSAndroid Build Coastguard Worker       received_dex_pc_moved_event(false),
48*795d594fSAndroid Build Coastguard Worker       received_field_read_event(false),
49*795d594fSAndroid Build Coastguard Worker       received_field_written_event(false),
50*795d594fSAndroid Build Coastguard Worker       received_field_written_object_event(false),
51*795d594fSAndroid Build Coastguard Worker       received_exception_thrown_event(false),
52*795d594fSAndroid Build Coastguard Worker       received_exception_handled_event(false),
53*795d594fSAndroid Build Coastguard Worker       received_branch_event(false),
54*795d594fSAndroid Build Coastguard Worker       received_watched_frame_pop(false) {}
55*795d594fSAndroid Build Coastguard Worker 
~TestInstrumentationListener()56*795d594fSAndroid Build Coastguard Worker   virtual ~TestInstrumentationListener() {}
57*795d594fSAndroid Build Coastguard Worker 
MethodEntered(Thread * thread,ArtMethod * method)58*795d594fSAndroid Build Coastguard Worker   void MethodEntered([[maybe_unused]] Thread* thread, [[maybe_unused]] ArtMethod* method) override
59*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
60*795d594fSAndroid Build Coastguard Worker     received_method_enter_event = true;
61*795d594fSAndroid Build Coastguard Worker   }
62*795d594fSAndroid Build Coastguard Worker 
MethodExited(Thread * thread,ArtMethod * method,instrumentation::OptionalFrame frame,MutableHandle<mirror::Object> & return_value)63*795d594fSAndroid Build Coastguard Worker   void MethodExited([[maybe_unused]] Thread* thread,
64*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] ArtMethod* method,
65*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] instrumentation::OptionalFrame frame,
66*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] MutableHandle<mirror::Object>& return_value) override
67*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
68*795d594fSAndroid Build Coastguard Worker     received_method_exit_object_event = true;
69*795d594fSAndroid Build Coastguard Worker   }
70*795d594fSAndroid Build Coastguard Worker 
MethodExited(Thread * thread,ArtMethod * method,instrumentation::OptionalFrame frame,JValue & return_value)71*795d594fSAndroid Build Coastguard Worker   void MethodExited([[maybe_unused]] Thread* thread,
72*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] ArtMethod* method,
73*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] instrumentation::OptionalFrame frame,
74*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] JValue& return_value) override
75*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
76*795d594fSAndroid Build Coastguard Worker     received_method_exit_event = true;
77*795d594fSAndroid Build Coastguard Worker   }
78*795d594fSAndroid Build Coastguard Worker 
MethodUnwind(Thread * thread,ArtMethod * method,uint32_t dex_pc)79*795d594fSAndroid Build Coastguard Worker   void MethodUnwind([[maybe_unused]] Thread* thread,
80*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] ArtMethod* method,
81*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] uint32_t dex_pc) override
82*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
83*795d594fSAndroid Build Coastguard Worker     received_method_unwind_event = true;
84*795d594fSAndroid Build Coastguard Worker   }
85*795d594fSAndroid Build Coastguard Worker 
DexPcMoved(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t new_dex_pc)86*795d594fSAndroid Build Coastguard Worker   void DexPcMoved([[maybe_unused]] Thread* thread,
87*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] Handle<mirror::Object> this_object,
88*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] ArtMethod* method,
89*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] uint32_t new_dex_pc) override
90*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
91*795d594fSAndroid Build Coastguard Worker     received_dex_pc_moved_event = true;
92*795d594fSAndroid Build Coastguard Worker   }
93*795d594fSAndroid Build Coastguard Worker 
FieldRead(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field)94*795d594fSAndroid Build Coastguard Worker   void FieldRead([[maybe_unused]] Thread* thread,
95*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] Handle<mirror::Object> this_object,
96*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] ArtMethod* method,
97*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] uint32_t dex_pc,
98*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] ArtField* field) override REQUIRES_SHARED(Locks::mutator_lock_) {
99*795d594fSAndroid Build Coastguard Worker     received_field_read_event = true;
100*795d594fSAndroid Build Coastguard Worker   }
101*795d594fSAndroid Build Coastguard Worker 
FieldWritten(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field,Handle<mirror::Object> field_value)102*795d594fSAndroid Build Coastguard Worker   void FieldWritten([[maybe_unused]] Thread* thread,
103*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] Handle<mirror::Object> this_object,
104*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] ArtMethod* method,
105*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] uint32_t dex_pc,
106*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] ArtField* field,
107*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] Handle<mirror::Object> field_value) override
108*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
109*795d594fSAndroid Build Coastguard Worker     received_field_written_object_event = true;
110*795d594fSAndroid Build Coastguard Worker   }
111*795d594fSAndroid Build Coastguard Worker 
FieldWritten(Thread * thread,Handle<mirror::Object> this_object,ArtMethod * method,uint32_t dex_pc,ArtField * field,const JValue & field_value)112*795d594fSAndroid Build Coastguard Worker   void FieldWritten([[maybe_unused]] Thread* thread,
113*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] Handle<mirror::Object> this_object,
114*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] ArtMethod* method,
115*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] uint32_t dex_pc,
116*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] ArtField* field,
117*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] const JValue& field_value) override
118*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
119*795d594fSAndroid Build Coastguard Worker     received_field_written_event = true;
120*795d594fSAndroid Build Coastguard Worker   }
121*795d594fSAndroid Build Coastguard Worker 
ExceptionThrown(Thread * thread,Handle<mirror::Throwable> exception_object)122*795d594fSAndroid Build Coastguard Worker   void ExceptionThrown([[maybe_unused]] Thread* thread,
123*795d594fSAndroid Build Coastguard Worker                        [[maybe_unused]] Handle<mirror::Throwable> exception_object) override
124*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
125*795d594fSAndroid Build Coastguard Worker     received_exception_thrown_event = true;
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker 
ExceptionHandled(Thread * self,Handle<mirror::Throwable> throwable)128*795d594fSAndroid Build Coastguard Worker   void ExceptionHandled([[maybe_unused]] Thread* self,
129*795d594fSAndroid Build Coastguard Worker                         [[maybe_unused]] Handle<mirror::Throwable> throwable) override
130*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
131*795d594fSAndroid Build Coastguard Worker     received_exception_handled_event = true;
132*795d594fSAndroid Build Coastguard Worker   }
133*795d594fSAndroid Build Coastguard Worker 
Branch(Thread * thread,ArtMethod * method,uint32_t dex_pc,int32_t dex_pc_offset)134*795d594fSAndroid Build Coastguard Worker   void Branch([[maybe_unused]] Thread* thread,
135*795d594fSAndroid Build Coastguard Worker               [[maybe_unused]] ArtMethod* method,
136*795d594fSAndroid Build Coastguard Worker               [[maybe_unused]] uint32_t dex_pc,
137*795d594fSAndroid Build Coastguard Worker               [[maybe_unused]] int32_t dex_pc_offset) override
138*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
139*795d594fSAndroid Build Coastguard Worker     received_branch_event = true;
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
WatchedFramePop(Thread * thread,const ShadowFrame & frame)142*795d594fSAndroid Build Coastguard Worker   void WatchedFramePop([[maybe_unused]] Thread* thread,
143*795d594fSAndroid Build Coastguard Worker                        [[maybe_unused]] const ShadowFrame& frame) override
144*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
145*795d594fSAndroid Build Coastguard Worker     received_watched_frame_pop  = true;
146*795d594fSAndroid Build Coastguard Worker   }
147*795d594fSAndroid Build Coastguard Worker 
Reset()148*795d594fSAndroid Build Coastguard Worker   void Reset() {
149*795d594fSAndroid Build Coastguard Worker     received_method_enter_event = false;
150*795d594fSAndroid Build Coastguard Worker     received_method_exit_event = false;
151*795d594fSAndroid Build Coastguard Worker     received_method_exit_object_event = false;
152*795d594fSAndroid Build Coastguard Worker     received_method_unwind_event = false;
153*795d594fSAndroid Build Coastguard Worker     received_dex_pc_moved_event = false;
154*795d594fSAndroid Build Coastguard Worker     received_field_read_event = false;
155*795d594fSAndroid Build Coastguard Worker     received_field_written_event = false;
156*795d594fSAndroid Build Coastguard Worker     received_field_written_object_event = false;
157*795d594fSAndroid Build Coastguard Worker     received_exception_thrown_event = false;
158*795d594fSAndroid Build Coastguard Worker     received_exception_handled_event = false;
159*795d594fSAndroid Build Coastguard Worker     received_branch_event = false;
160*795d594fSAndroid Build Coastguard Worker     received_watched_frame_pop = false;
161*795d594fSAndroid Build Coastguard Worker   }
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker   bool received_method_enter_event;
164*795d594fSAndroid Build Coastguard Worker   bool received_method_exit_event;
165*795d594fSAndroid Build Coastguard Worker   bool received_method_exit_object_event;
166*795d594fSAndroid Build Coastguard Worker   bool received_method_unwind_event;
167*795d594fSAndroid Build Coastguard Worker   bool received_dex_pc_moved_event;
168*795d594fSAndroid Build Coastguard Worker   bool received_field_read_event;
169*795d594fSAndroid Build Coastguard Worker   bool received_field_written_event;
170*795d594fSAndroid Build Coastguard Worker   bool received_field_written_object_event;
171*795d594fSAndroid Build Coastguard Worker   bool received_exception_thrown_event;
172*795d594fSAndroid Build Coastguard Worker   bool received_exception_handled_event;
173*795d594fSAndroid Build Coastguard Worker   bool received_branch_event;
174*795d594fSAndroid Build Coastguard Worker   bool received_watched_frame_pop;
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker  private:
177*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
178*795d594fSAndroid Build Coastguard Worker };
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker class InstrumentationTest : public CommonRuntimeTest {
181*795d594fSAndroid Build Coastguard Worker  public:
182*795d594fSAndroid Build Coastguard Worker   // Unique keys used to test Instrumentation::ConfigureStubs.
183*795d594fSAndroid Build Coastguard Worker   static constexpr const char* kClientOneKey = "TestClient1";
184*795d594fSAndroid Build Coastguard Worker   static constexpr const char* kClientTwoKey = "TestClient2";
185*795d594fSAndroid Build Coastguard Worker 
InstrumentationTest()186*795d594fSAndroid Build Coastguard Worker   InstrumentationTest() {
187*795d594fSAndroid Build Coastguard Worker     use_boot_image_ = true;  // Make the Runtime creation cheaper.
188*795d594fSAndroid Build Coastguard Worker   }
189*795d594fSAndroid Build Coastguard Worker 
CheckConfigureStubs(const char * key,Instrumentation::InstrumentationLevel level)190*795d594fSAndroid Build Coastguard Worker   void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
191*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
192*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
193*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(soa.Self(), ThreadState::kSuspended);
194*795d594fSAndroid Build Coastguard Worker     gc::ScopedGCCriticalSection gcs(soa.Self(),
195*795d594fSAndroid Build Coastguard Worker                                     gc::kGcCauseInstrumentation,
196*795d594fSAndroid Build Coastguard Worker                                     gc::kCollectorTypeInstrumentation);
197*795d594fSAndroid Build Coastguard Worker     ScopedSuspendAll ssa("Instrumentation::ConfigureStubs");
198*795d594fSAndroid Build Coastguard Worker     instr->ConfigureStubs(key, level, /*try_switch_to_non_debuggable=*/false);
199*795d594fSAndroid Build Coastguard Worker   }
200*795d594fSAndroid Build Coastguard Worker 
GetCurrentInstrumentationLevel()201*795d594fSAndroid Build Coastguard Worker   Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
202*795d594fSAndroid Build Coastguard Worker     return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
203*795d594fSAndroid Build Coastguard Worker   }
204*795d594fSAndroid Build Coastguard Worker 
GetInstrumentationUserCount()205*795d594fSAndroid Build Coastguard Worker   size_t GetInstrumentationUserCount() {
206*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
207*795d594fSAndroid Build Coastguard Worker     return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
208*795d594fSAndroid Build Coastguard Worker   }
209*795d594fSAndroid Build Coastguard Worker 
TestEvent(uint32_t instrumentation_event)210*795d594fSAndroid Build Coastguard Worker   void TestEvent(uint32_t instrumentation_event) {
211*795d594fSAndroid Build Coastguard Worker     TestEvent(instrumentation_event, nullptr, nullptr, false);
212*795d594fSAndroid Build Coastguard Worker   }
213*795d594fSAndroid Build Coastguard Worker 
TestEvent(uint32_t instrumentation_event,ArtMethod * event_method,ArtField * event_field,bool with_object)214*795d594fSAndroid Build Coastguard Worker   void TestEvent(uint32_t instrumentation_event,
215*795d594fSAndroid Build Coastguard Worker                  ArtMethod* event_method,
216*795d594fSAndroid Build Coastguard Worker                  ArtField* event_field,
217*795d594fSAndroid Build Coastguard Worker                  bool with_object) {
218*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
219*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
220*795d594fSAndroid Build Coastguard Worker     TestInstrumentationListener listener;
221*795d594fSAndroid Build Coastguard Worker     {
222*795d594fSAndroid Build Coastguard Worker       ScopedThreadSuspension sts(soa.Self(), ThreadState::kSuspended);
223*795d594fSAndroid Build Coastguard Worker       ScopedSuspendAll ssa("Add instrumentation listener");
224*795d594fSAndroid Build Coastguard Worker       instr->AddListener(&listener, instrumentation_event);
225*795d594fSAndroid Build Coastguard Worker     }
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker     mirror::Object* const event_obj = nullptr;
228*795d594fSAndroid Build Coastguard Worker     const uint32_t event_dex_pc = 0;
229*795d594fSAndroid Build Coastguard Worker     ShadowFrameAllocaUniquePtr test_frame = CREATE_SHADOW_FRAME(0, event_method, 0);
230*795d594fSAndroid Build Coastguard Worker 
231*795d594fSAndroid Build Coastguard Worker     // Check the listener is registered and is notified of the event.
232*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
233*795d594fSAndroid Build Coastguard Worker     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
234*795d594fSAndroid Build Coastguard Worker     ReportEvent(instr,
235*795d594fSAndroid Build Coastguard Worker                 instrumentation_event,
236*795d594fSAndroid Build Coastguard Worker                 soa.Self(),
237*795d594fSAndroid Build Coastguard Worker                 event_method,
238*795d594fSAndroid Build Coastguard Worker                 event_obj,
239*795d594fSAndroid Build Coastguard Worker                 event_field,
240*795d594fSAndroid Build Coastguard Worker                 event_dex_pc,
241*795d594fSAndroid Build Coastguard Worker                 *test_frame);
242*795d594fSAndroid Build Coastguard Worker     EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker     listener.Reset();
245*795d594fSAndroid Build Coastguard Worker     {
246*795d594fSAndroid Build Coastguard Worker       ScopedThreadSuspension sts(soa.Self(), ThreadState::kSuspended);
247*795d594fSAndroid Build Coastguard Worker       ScopedSuspendAll ssa("Remove instrumentation listener");
248*795d594fSAndroid Build Coastguard Worker       instr->RemoveListener(&listener, instrumentation_event);
249*795d594fSAndroid Build Coastguard Worker     }
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker     // Check the listener is not registered and is not notified of the event.
252*795d594fSAndroid Build Coastguard Worker     EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
253*795d594fSAndroid Build Coastguard Worker     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
254*795d594fSAndroid Build Coastguard Worker     ReportEvent(instr,
255*795d594fSAndroid Build Coastguard Worker                 instrumentation_event,
256*795d594fSAndroid Build Coastguard Worker                 soa.Self(),
257*795d594fSAndroid Build Coastguard Worker                 event_method,
258*795d594fSAndroid Build Coastguard Worker                 event_obj,
259*795d594fSAndroid Build Coastguard Worker                 event_field,
260*795d594fSAndroid Build Coastguard Worker                 event_dex_pc,
261*795d594fSAndroid Build Coastguard Worker                 *test_frame);
262*795d594fSAndroid Build Coastguard Worker     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event, with_object));
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker 
DeoptimizeMethod(Thread * self,ArtMethod * method)265*795d594fSAndroid Build Coastguard Worker   void DeoptimizeMethod(Thread* self, ArtMethod* method)
266*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
267*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
268*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
269*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
270*795d594fSAndroid Build Coastguard Worker     gc::ScopedGCCriticalSection gcs(self,
271*795d594fSAndroid Build Coastguard Worker                                     gc::kGcCauseInstrumentation,
272*795d594fSAndroid Build Coastguard Worker                                     gc::kCollectorTypeInstrumentation);
273*795d594fSAndroid Build Coastguard Worker     ScopedSuspendAll ssa("Single method deoptimization");
274*795d594fSAndroid Build Coastguard Worker     instrumentation->Deoptimize(method);
275*795d594fSAndroid Build Coastguard Worker   }
276*795d594fSAndroid Build Coastguard Worker 
UndeoptimizeMethod(Thread * self,ArtMethod * method,const char * key,bool disable_deoptimization)277*795d594fSAndroid Build Coastguard Worker   void UndeoptimizeMethod(Thread* self, ArtMethod* method,
278*795d594fSAndroid Build Coastguard Worker                           const char* key, bool disable_deoptimization)
279*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
280*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
281*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
282*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
283*795d594fSAndroid Build Coastguard Worker     gc::ScopedGCCriticalSection gcs(self,
284*795d594fSAndroid Build Coastguard Worker                                     gc::kGcCauseInstrumentation,
285*795d594fSAndroid Build Coastguard Worker                                     gc::kCollectorTypeInstrumentation);
286*795d594fSAndroid Build Coastguard Worker     ScopedSuspendAll ssa("Single method undeoptimization");
287*795d594fSAndroid Build Coastguard Worker     instrumentation->Undeoptimize(method);
288*795d594fSAndroid Build Coastguard Worker     if (disable_deoptimization) {
289*795d594fSAndroid Build Coastguard Worker       instrumentation->DisableDeoptimization(key, /*try_switch_to_non_debuggable=*/false);
290*795d594fSAndroid Build Coastguard Worker     }
291*795d594fSAndroid Build Coastguard Worker   }
292*795d594fSAndroid Build Coastguard Worker 
DeoptimizeEverything(Thread * self,const char * key)293*795d594fSAndroid Build Coastguard Worker   void DeoptimizeEverything(Thread* self, const char* key)
294*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) {
295*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
296*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
297*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
298*795d594fSAndroid Build Coastguard Worker     gc::ScopedGCCriticalSection gcs(self,
299*795d594fSAndroid Build Coastguard Worker                                     gc::kGcCauseInstrumentation,
300*795d594fSAndroid Build Coastguard Worker                                     gc::kCollectorTypeInstrumentation);
301*795d594fSAndroid Build Coastguard Worker     ScopedSuspendAll ssa("Full deoptimization");
302*795d594fSAndroid Build Coastguard Worker     instrumentation->DeoptimizeEverything(key);
303*795d594fSAndroid Build Coastguard Worker   }
304*795d594fSAndroid Build Coastguard Worker 
UndeoptimizeEverything(Thread * self,const char * key,bool disable_deoptimization)305*795d594fSAndroid Build Coastguard Worker   void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
306*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) {
307*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
308*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
309*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
310*795d594fSAndroid Build Coastguard Worker     gc::ScopedGCCriticalSection gcs(self,
311*795d594fSAndroid Build Coastguard Worker                                     gc::kGcCauseInstrumentation,
312*795d594fSAndroid Build Coastguard Worker                                     gc::kCollectorTypeInstrumentation);
313*795d594fSAndroid Build Coastguard Worker     ScopedSuspendAll ssa("Full undeoptimization");
314*795d594fSAndroid Build Coastguard Worker     instrumentation->UndeoptimizeEverything(key);
315*795d594fSAndroid Build Coastguard Worker     if (disable_deoptimization) {
316*795d594fSAndroid Build Coastguard Worker       instrumentation->DisableDeoptimization(key, /*try_switch_to_non_debuggable=*/false);
317*795d594fSAndroid Build Coastguard Worker     }
318*795d594fSAndroid Build Coastguard Worker   }
319*795d594fSAndroid Build Coastguard Worker 
EnableMethodTracing(Thread * self,const char * key,bool needs_interpreter)320*795d594fSAndroid Build Coastguard Worker   void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
321*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) {
322*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
323*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
324*795d594fSAndroid Build Coastguard Worker     TestInstrumentationListener listener;
325*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
326*795d594fSAndroid Build Coastguard Worker     gc::ScopedGCCriticalSection gcs(self,
327*795d594fSAndroid Build Coastguard Worker                                     gc::kGcCauseInstrumentation,
328*795d594fSAndroid Build Coastguard Worker                                     gc::kCollectorTypeInstrumentation);
329*795d594fSAndroid Build Coastguard Worker     ScopedSuspendAll ssa("EnableMethodTracing");
330*795d594fSAndroid Build Coastguard Worker     instrumentation->EnableMethodTracing(key, &listener, needs_interpreter);
331*795d594fSAndroid Build Coastguard Worker   }
332*795d594fSAndroid Build Coastguard Worker 
DisableMethodTracing(Thread * self,const char * key)333*795d594fSAndroid Build Coastguard Worker   void DisableMethodTracing(Thread* self, const char* key)
334*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) {
335*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
336*795d594fSAndroid Build Coastguard Worker     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
337*795d594fSAndroid Build Coastguard Worker     ScopedThreadSuspension sts(self, ThreadState::kSuspended);
338*795d594fSAndroid Build Coastguard Worker     gc::ScopedGCCriticalSection gcs(self,
339*795d594fSAndroid Build Coastguard Worker                                     gc::kGcCauseInstrumentation,
340*795d594fSAndroid Build Coastguard Worker                                     gc::kCollectorTypeInstrumentation);
341*795d594fSAndroid Build Coastguard Worker     ScopedSuspendAll ssa("EnableMethodTracing");
342*795d594fSAndroid Build Coastguard Worker     instrumentation->DisableMethodTracing(key);
343*795d594fSAndroid Build Coastguard Worker   }
344*795d594fSAndroid Build Coastguard Worker 
345*795d594fSAndroid Build Coastguard Worker  private:
HasEventListener(const instrumentation::Instrumentation * instr,uint32_t event_type)346*795d594fSAndroid Build Coastguard Worker   static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
347*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
348*795d594fSAndroid Build Coastguard Worker     switch (event_type) {
349*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodEntered:
350*795d594fSAndroid Build Coastguard Worker         return instr->HasMethodEntryListeners();
351*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodExited:
352*795d594fSAndroid Build Coastguard Worker         return instr->HasMethodExitListeners();
353*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodUnwind:
354*795d594fSAndroid Build Coastguard Worker         return instr->HasMethodUnwindListeners();
355*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kDexPcMoved:
356*795d594fSAndroid Build Coastguard Worker         return instr->HasDexPcListeners();
357*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kFieldRead:
358*795d594fSAndroid Build Coastguard Worker         return instr->HasFieldReadListeners();
359*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kFieldWritten:
360*795d594fSAndroid Build Coastguard Worker         return instr->HasFieldWriteListeners();
361*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kExceptionThrown:
362*795d594fSAndroid Build Coastguard Worker         return instr->HasExceptionThrownListeners();
363*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kExceptionHandled:
364*795d594fSAndroid Build Coastguard Worker         return instr->HasExceptionHandledListeners();
365*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kBranch:
366*795d594fSAndroid Build Coastguard Worker         return instr->HasBranchListeners();
367*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kWatchedFramePop:
368*795d594fSAndroid Build Coastguard Worker         return instr->HasWatchedFramePopListeners();
369*795d594fSAndroid Build Coastguard Worker       default:
370*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unknown instrumentation event " << event_type;
371*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
372*795d594fSAndroid Build Coastguard Worker     }
373*795d594fSAndroid Build Coastguard Worker   }
374*795d594fSAndroid Build Coastguard Worker 
ReportEvent(const instrumentation::Instrumentation * instr,uint32_t event_type,Thread * self,ArtMethod * method,mirror::Object * obj,ArtField * field,uint32_t dex_pc,const ShadowFrame & frame)375*795d594fSAndroid Build Coastguard Worker   static void ReportEvent(const instrumentation::Instrumentation* instr,
376*795d594fSAndroid Build Coastguard Worker                           uint32_t event_type,
377*795d594fSAndroid Build Coastguard Worker                           Thread* self,
378*795d594fSAndroid Build Coastguard Worker                           ArtMethod* method,
379*795d594fSAndroid Build Coastguard Worker                           mirror::Object* obj,
380*795d594fSAndroid Build Coastguard Worker                           ArtField* field,
381*795d594fSAndroid Build Coastguard Worker                           uint32_t dex_pc,
382*795d594fSAndroid Build Coastguard Worker                           const ShadowFrame& frame)
383*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
384*795d594fSAndroid Build Coastguard Worker     switch (event_type) {
385*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodEntered:
386*795d594fSAndroid Build Coastguard Worker         instr->MethodEnterEvent(self, method);
387*795d594fSAndroid Build Coastguard Worker         break;
388*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodExited: {
389*795d594fSAndroid Build Coastguard Worker         JValue value;
390*795d594fSAndroid Build Coastguard Worker         instr->MethodExitEvent(self, method, {}, value);
391*795d594fSAndroid Build Coastguard Worker         break;
392*795d594fSAndroid Build Coastguard Worker       }
393*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodUnwind:
394*795d594fSAndroid Build Coastguard Worker         instr->MethodUnwindEvent(self, method, dex_pc);
395*795d594fSAndroid Build Coastguard Worker         break;
396*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kDexPcMoved:
397*795d594fSAndroid Build Coastguard Worker         instr->DexPcMovedEvent(self, obj, method, dex_pc);
398*795d594fSAndroid Build Coastguard Worker         break;
399*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kFieldRead:
400*795d594fSAndroid Build Coastguard Worker         instr->FieldReadEvent(self, obj, method, dex_pc, field);
401*795d594fSAndroid Build Coastguard Worker         break;
402*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kFieldWritten: {
403*795d594fSAndroid Build Coastguard Worker         JValue value;
404*795d594fSAndroid Build Coastguard Worker         instr->FieldWriteEvent(self, obj, method, dex_pc, field, value);
405*795d594fSAndroid Build Coastguard Worker         break;
406*795d594fSAndroid Build Coastguard Worker       }
407*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kExceptionThrown: {
408*795d594fSAndroid Build Coastguard Worker         ThrowArithmeticExceptionDivideByZero();
409*795d594fSAndroid Build Coastguard Worker         mirror::Throwable* event_exception = self->GetException();
410*795d594fSAndroid Build Coastguard Worker         instr->ExceptionThrownEvent(self, event_exception);
411*795d594fSAndroid Build Coastguard Worker         self->ClearException();
412*795d594fSAndroid Build Coastguard Worker         break;
413*795d594fSAndroid Build Coastguard Worker       }
414*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kBranch:
415*795d594fSAndroid Build Coastguard Worker         instr->Branch(self, method, dex_pc, -1);
416*795d594fSAndroid Build Coastguard Worker         break;
417*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kWatchedFramePop:
418*795d594fSAndroid Build Coastguard Worker         instr->WatchedFramePopped(self, frame);
419*795d594fSAndroid Build Coastguard Worker         break;
420*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kExceptionHandled: {
421*795d594fSAndroid Build Coastguard Worker         ThrowArithmeticExceptionDivideByZero();
422*795d594fSAndroid Build Coastguard Worker         mirror::Throwable* event_exception = self->GetException();
423*795d594fSAndroid Build Coastguard Worker         self->ClearException();
424*795d594fSAndroid Build Coastguard Worker         instr->ExceptionHandledEvent(self, event_exception);
425*795d594fSAndroid Build Coastguard Worker         break;
426*795d594fSAndroid Build Coastguard Worker       }
427*795d594fSAndroid Build Coastguard Worker       default:
428*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unknown instrumentation event " << event_type;
429*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
430*795d594fSAndroid Build Coastguard Worker     }
431*795d594fSAndroid Build Coastguard Worker   }
432*795d594fSAndroid Build Coastguard Worker 
DidListenerReceiveEvent(const TestInstrumentationListener & listener,uint32_t event_type,bool with_object)433*795d594fSAndroid Build Coastguard Worker   static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
434*795d594fSAndroid Build Coastguard Worker                                       uint32_t event_type,
435*795d594fSAndroid Build Coastguard Worker                                       bool with_object) {
436*795d594fSAndroid Build Coastguard Worker     switch (event_type) {
437*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodEntered:
438*795d594fSAndroid Build Coastguard Worker         return listener.received_method_enter_event;
439*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodExited:
440*795d594fSAndroid Build Coastguard Worker         return (!with_object && listener.received_method_exit_event) ||
441*795d594fSAndroid Build Coastguard Worker             (with_object && listener.received_method_exit_object_event);
442*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kMethodUnwind:
443*795d594fSAndroid Build Coastguard Worker         return listener.received_method_unwind_event;
444*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kDexPcMoved:
445*795d594fSAndroid Build Coastguard Worker         return listener.received_dex_pc_moved_event;
446*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kFieldRead:
447*795d594fSAndroid Build Coastguard Worker         return listener.received_field_read_event;
448*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kFieldWritten:
449*795d594fSAndroid Build Coastguard Worker         return (!with_object && listener.received_field_written_event) ||
450*795d594fSAndroid Build Coastguard Worker             (with_object && listener.received_field_written_object_event);
451*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kExceptionThrown:
452*795d594fSAndroid Build Coastguard Worker         return listener.received_exception_thrown_event;
453*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kExceptionHandled:
454*795d594fSAndroid Build Coastguard Worker         return listener.received_exception_handled_event;
455*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kBranch:
456*795d594fSAndroid Build Coastguard Worker         return listener.received_branch_event;
457*795d594fSAndroid Build Coastguard Worker       case instrumentation::Instrumentation::kWatchedFramePop:
458*795d594fSAndroid Build Coastguard Worker         return listener.received_watched_frame_pop;
459*795d594fSAndroid Build Coastguard Worker       default:
460*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unknown instrumentation event " << event_type;
461*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
462*795d594fSAndroid Build Coastguard Worker     }
463*795d594fSAndroid Build Coastguard Worker   }
464*795d594fSAndroid Build Coastguard Worker };
465*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,NoInstrumentation)466*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, NoInstrumentation) {
467*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
468*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
469*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(instr, nullptr);
470*795d594fSAndroid Build Coastguard Worker 
471*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->RunExitHooks());
472*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->EntryExitStubsInstalled());
473*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
474*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->NeedsSlowInterpreterForListeners());
475*795d594fSAndroid Build Coastguard Worker 
476*795d594fSAndroid Build Coastguard Worker   // Check there is no registered listener.
477*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->HasDexPcListeners());
478*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->HasExceptionThrownListeners());
479*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->HasExceptionHandledListeners());
480*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->HasFieldReadListeners());
481*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->HasFieldWriteListeners());
482*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->HasMethodEntryListeners());
483*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->HasMethodExitListeners());
484*795d594fSAndroid Build Coastguard Worker }
485*795d594fSAndroid Build Coastguard Worker 
486*795d594fSAndroid Build Coastguard Worker // Test instrumentation listeners for each event.
TEST_F(InstrumentationTest,MethodEntryEvent)487*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MethodEntryEvent) {
488*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
489*795d594fSAndroid Build Coastguard Worker   jobject class_loader = LoadDex("Instrumentation");
490*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
491*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
492*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
493*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
494*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader);
495*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(klass != nullptr);
496*795d594fSAndroid Build Coastguard Worker   ArtMethod* method =
497*795d594fSAndroid Build Coastguard Worker       klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize);
498*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method != nullptr);
499*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method->IsDirect());
500*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method->GetDeclaringClass() == klass);
501*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kMethodEntered,
502*795d594fSAndroid Build Coastguard Worker             /*event_method=*/ method,
503*795d594fSAndroid Build Coastguard Worker             /*event_field=*/ nullptr,
504*795d594fSAndroid Build Coastguard Worker             /*with_object=*/ true);
505*795d594fSAndroid Build Coastguard Worker }
506*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MethodExitObjectEvent)507*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MethodExitObjectEvent) {
508*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
509*795d594fSAndroid Build Coastguard Worker   jobject class_loader = LoadDex("Instrumentation");
510*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
511*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
512*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
513*795d594fSAndroid Build Coastguard Worker   MutableHandle<mirror::ClassLoader> loader(
514*795d594fSAndroid Build Coastguard Worker       hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
515*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader);
516*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(klass != nullptr);
517*795d594fSAndroid Build Coastguard Worker   ArtMethod* method =
518*795d594fSAndroid Build Coastguard Worker       klass->FindClassMethod("returnReference", "()Ljava/lang/Object;", kRuntimePointerSize);
519*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method != nullptr);
520*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method->IsDirect());
521*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method->GetDeclaringClass() == klass);
522*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kMethodExited,
523*795d594fSAndroid Build Coastguard Worker             /*event_method=*/ method,
524*795d594fSAndroid Build Coastguard Worker             /*event_field=*/ nullptr,
525*795d594fSAndroid Build Coastguard Worker             /*with_object=*/ true);
526*795d594fSAndroid Build Coastguard Worker }
527*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MethodExitPrimEvent)528*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MethodExitPrimEvent) {
529*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
530*795d594fSAndroid Build Coastguard Worker   jobject class_loader = LoadDex("Instrumentation");
531*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
532*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
533*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
534*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
535*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader);
536*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(klass != nullptr);
537*795d594fSAndroid Build Coastguard Worker   ArtMethod* method = klass->FindClassMethod("returnPrimitive", "()I", kRuntimePointerSize);
538*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method != nullptr);
539*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method->IsDirect());
540*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method->GetDeclaringClass() == klass);
541*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kMethodExited,
542*795d594fSAndroid Build Coastguard Worker             /*event_method=*/ method,
543*795d594fSAndroid Build Coastguard Worker             /*event_field=*/ nullptr,
544*795d594fSAndroid Build Coastguard Worker             /*with_object=*/ false);
545*795d594fSAndroid Build Coastguard Worker }
546*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MethodUnwindEvent)547*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MethodUnwindEvent) {
548*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kMethodUnwind);
549*795d594fSAndroid Build Coastguard Worker }
550*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,DexPcMovedEvent)551*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, DexPcMovedEvent) {
552*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kDexPcMoved);
553*795d594fSAndroid Build Coastguard Worker }
554*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,FieldReadEvent)555*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, FieldReadEvent) {
556*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kFieldRead);
557*795d594fSAndroid Build Coastguard Worker }
558*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,WatchedFramePop)559*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, WatchedFramePop) {
560*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kWatchedFramePop);
561*795d594fSAndroid Build Coastguard Worker }
562*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,FieldWriteObjectEvent)563*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, FieldWriteObjectEvent) {
564*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
565*795d594fSAndroid Build Coastguard Worker   jobject class_loader = LoadDex("Instrumentation");
566*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
567*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
568*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
569*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
570*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader);
571*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(klass != nullptr);
572*795d594fSAndroid Build Coastguard Worker   ArtField* field = klass->FindDeclaredStaticField("referenceField", "Ljava/lang/Object;");
573*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(field != nullptr);
574*795d594fSAndroid Build Coastguard Worker 
575*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kFieldWritten,
576*795d594fSAndroid Build Coastguard Worker             /*event_method=*/ nullptr,
577*795d594fSAndroid Build Coastguard Worker             /*event_field=*/ field,
578*795d594fSAndroid Build Coastguard Worker             /*with_object=*/ true);
579*795d594fSAndroid Build Coastguard Worker }
580*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,FieldWritePrimEvent)581*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, FieldWritePrimEvent) {
582*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
583*795d594fSAndroid Build Coastguard Worker   jobject class_loader = LoadDex("Instrumentation");
584*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
585*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
586*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
587*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
588*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader);
589*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(klass != nullptr);
590*795d594fSAndroid Build Coastguard Worker   ArtField* field = klass->FindDeclaredStaticField("primitiveField", "I");
591*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(field != nullptr);
592*795d594fSAndroid Build Coastguard Worker 
593*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kFieldWritten,
594*795d594fSAndroid Build Coastguard Worker             /*event_method=*/ nullptr,
595*795d594fSAndroid Build Coastguard Worker             /*event_field=*/ field,
596*795d594fSAndroid Build Coastguard Worker             /*with_object=*/ false);
597*795d594fSAndroid Build Coastguard Worker }
598*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ExceptionHandledEvent)599*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, ExceptionHandledEvent) {
600*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kExceptionHandled);
601*795d594fSAndroid Build Coastguard Worker }
602*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ExceptionThrownEvent)603*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, ExceptionThrownEvent) {
604*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kExceptionThrown);
605*795d594fSAndroid Build Coastguard Worker }
606*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,BranchEvent)607*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, BranchEvent) {
608*795d594fSAndroid Build Coastguard Worker   TestEvent(instrumentation::Instrumentation::kBranch);
609*795d594fSAndroid Build Coastguard Worker }
610*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,DeoptimizeDirectMethod)611*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
612*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
613*795d594fSAndroid Build Coastguard Worker   jobject class_loader = LoadDex("Instrumentation");
614*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
615*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
616*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
617*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
618*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
619*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader);
620*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(klass != nullptr);
621*795d594fSAndroid Build Coastguard Worker   ArtMethod* method_to_deoptimize =
622*795d594fSAndroid Build Coastguard Worker       klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize);
623*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method_to_deoptimize != nullptr);
624*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method_to_deoptimize->IsDirect());
625*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method_to_deoptimize->GetDeclaringClass() == klass);
626*795d594fSAndroid Build Coastguard Worker 
627*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
628*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
629*795d594fSAndroid Build Coastguard Worker 
630*795d594fSAndroid Build Coastguard Worker   DeoptimizeMethod(soa.Self(), method_to_deoptimize);
631*795d594fSAndroid Build Coastguard Worker 
632*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
633*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->RunExitHooks());
634*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
635*795d594fSAndroid Build Coastguard Worker 
636*795d594fSAndroid Build Coastguard Worker   constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
637*795d594fSAndroid Build Coastguard Worker   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
638*795d594fSAndroid Build Coastguard Worker 
639*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
640*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
641*795d594fSAndroid Build Coastguard Worker }
642*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,FullDeoptimization)643*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, FullDeoptimization) {
644*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
645*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
646*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
647*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
648*795d594fSAndroid Build Coastguard Worker 
649*795d594fSAndroid Build Coastguard Worker   constexpr const char* instrumentation_key = "FullDeoptimization";
650*795d594fSAndroid Build Coastguard Worker   DeoptimizeEverything(soa.Self(), instrumentation_key);
651*795d594fSAndroid Build Coastguard Worker 
652*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
653*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->RunExitHooks());
654*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->InterpreterStubsInstalled());
655*795d594fSAndroid Build Coastguard Worker 
656*795d594fSAndroid Build Coastguard Worker   UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
657*795d594fSAndroid Build Coastguard Worker 
658*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
659*795d594fSAndroid Build Coastguard Worker }
660*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MixedDeoptimization)661*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MixedDeoptimization) {
662*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
663*795d594fSAndroid Build Coastguard Worker   jobject class_loader = LoadDex("Instrumentation");
664*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
665*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
666*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
667*795d594fSAndroid Build Coastguard Worker   StackHandleScope<1> hs(soa.Self());
668*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
669*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = FindClass("LInstrumentation;", loader);
670*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(klass != nullptr);
671*795d594fSAndroid Build Coastguard Worker   ArtMethod* method_to_deoptimize =
672*795d594fSAndroid Build Coastguard Worker       klass->FindClassMethod("instanceMethod", "()V", kRuntimePointerSize);
673*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method_to_deoptimize != nullptr);
674*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method_to_deoptimize->IsDirect());
675*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(method_to_deoptimize->GetDeclaringClass() == klass);
676*795d594fSAndroid Build Coastguard Worker 
677*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
678*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
679*795d594fSAndroid Build Coastguard Worker 
680*795d594fSAndroid Build Coastguard Worker   DeoptimizeMethod(soa.Self(), method_to_deoptimize);
681*795d594fSAndroid Build Coastguard Worker   // Deoptimizing a method does not change instrumentation level.
682*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
683*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
684*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
685*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->RunExitHooks());
686*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
687*795d594fSAndroid Build Coastguard Worker 
688*795d594fSAndroid Build Coastguard Worker   constexpr const char* instrumentation_key = "MixedDeoptimization";
689*795d594fSAndroid Build Coastguard Worker   DeoptimizeEverything(soa.Self(), instrumentation_key);
690*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
691*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
692*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
693*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->RunExitHooks());
694*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
695*795d594fSAndroid Build Coastguard Worker 
696*795d594fSAndroid Build Coastguard Worker   UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
697*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
698*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
699*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
700*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->RunExitHooks());
701*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
702*795d594fSAndroid Build Coastguard Worker 
703*795d594fSAndroid Build Coastguard Worker   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
704*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
705*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
706*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
707*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
708*795d594fSAndroid Build Coastguard Worker }
709*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MethodTracing_Interpreter)710*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
711*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
712*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
713*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
714*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
715*795d594fSAndroid Build Coastguard Worker 
716*795d594fSAndroid Build Coastguard Worker   constexpr const char* instrumentation_key = "MethodTracing";
717*795d594fSAndroid Build Coastguard Worker   EnableMethodTracing(soa.Self(), instrumentation_key, true);
718*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
719*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
720*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
721*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->RunExitHooks());
722*795d594fSAndroid Build Coastguard Worker 
723*795d594fSAndroid Build Coastguard Worker   DisableMethodTracing(soa.Self(), instrumentation_key);
724*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
725*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
726*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
727*795d594fSAndroid Build Coastguard Worker }
728*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MethodTracing_InstrumentationEntryExitStubs)729*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
730*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(Thread::Current());
731*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
732*795d594fSAndroid Build Coastguard Worker   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
733*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
734*795d594fSAndroid Build Coastguard Worker 
735*795d594fSAndroid Build Coastguard Worker   constexpr const char* instrumentation_key = "MethodTracing";
736*795d594fSAndroid Build Coastguard Worker   EnableMethodTracing(soa.Self(), instrumentation_key, false);
737*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks,
738*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
739*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
740*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(instr->RunExitHooks());
741*795d594fSAndroid Build Coastguard Worker 
742*795d594fSAndroid Build Coastguard Worker   DisableMethodTracing(soa.Self(), instrumentation_key);
743*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
744*795d594fSAndroid Build Coastguard Worker             GetCurrentInstrumentationLevel());
745*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
746*795d594fSAndroid Build Coastguard Worker }
747*795d594fSAndroid Build Coastguard Worker 
748*795d594fSAndroid Build Coastguard Worker // We use a macro to print the line number where the test is failing.
749*795d594fSAndroid Build Coastguard Worker #define CHECK_INSTRUMENTATION(_level, _user_count)                                      \
750*795d594fSAndroid Build Coastguard Worker   do {                                                                                  \
751*795d594fSAndroid Build Coastguard Worker     Instrumentation* const instr = Runtime::Current()->GetInstrumentation();            \
752*795d594fSAndroid Build Coastguard Worker     bool interpreter =                                                                  \
753*795d594fSAndroid Build Coastguard Worker       ((_level) == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);  \
754*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(_level, GetCurrentInstrumentationLevel());                                \
755*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(_user_count, GetInstrumentationUserCount());                              \
756*795d594fSAndroid Build Coastguard Worker     if (instr->IsForcedInterpretOnly()) {                                               \
757*795d594fSAndroid Build Coastguard Worker       EXPECT_TRUE(instr->InterpretOnly());                                              \
758*795d594fSAndroid Build Coastguard Worker     } else if (interpreter) {                                                           \
759*795d594fSAndroid Build Coastguard Worker       EXPECT_TRUE(instr->InterpretOnly());                                              \
760*795d594fSAndroid Build Coastguard Worker     } else {                                                                            \
761*795d594fSAndroid Build Coastguard Worker       EXPECT_FALSE(instr->InterpretOnly());                                             \
762*795d594fSAndroid Build Coastguard Worker     }                                                                                   \
763*795d594fSAndroid Build Coastguard Worker     if (interpreter) {                                                                  \
764*795d594fSAndroid Build Coastguard Worker       EXPECT_TRUE(instr->AreAllMethodsDeoptimized());                                   \
765*795d594fSAndroid Build Coastguard Worker     } else {                                                                            \
766*795d594fSAndroid Build Coastguard Worker       EXPECT_FALSE(instr->AreAllMethodsDeoptimized());                                  \
767*795d594fSAndroid Build Coastguard Worker     }                                                                                   \
768*795d594fSAndroid Build Coastguard Worker   } while (false)
769*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ConfigureStubs_Nothing)770*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
771*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
772*795d594fSAndroid Build Coastguard Worker 
773*795d594fSAndroid Build Coastguard Worker   // Check no-op.
774*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
775*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
776*795d594fSAndroid Build Coastguard Worker }
777*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubs)778*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
779*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
780*795d594fSAndroid Build Coastguard Worker 
781*795d594fSAndroid Build Coastguard Worker   // Check we can switch to instrumentation stubs
782*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
783*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
784*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
785*795d594fSAndroid Build Coastguard Worker 
786*795d594fSAndroid Build Coastguard Worker   // Check we can disable instrumentation.
787*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
788*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
789*795d594fSAndroid Build Coastguard Worker }
790*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ConfigureStubs_Interpreter)791*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
792*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
793*795d594fSAndroid Build Coastguard Worker 
794*795d594fSAndroid Build Coastguard Worker   // Check we can switch to interpreter
795*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
796*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
797*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
798*795d594fSAndroid Build Coastguard Worker 
799*795d594fSAndroid Build Coastguard Worker   // Check we can disable instrumentation.
800*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
801*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
802*795d594fSAndroid Build Coastguard Worker }
803*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreter)804*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
805*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
806*795d594fSAndroid Build Coastguard Worker 
807*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs.
808*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
809*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
810*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
811*795d594fSAndroid Build Coastguard Worker 
812*795d594fSAndroid Build Coastguard Worker   // Configure stubs with interpreter.
813*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
814*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
815*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
816*795d594fSAndroid Build Coastguard Worker 
817*795d594fSAndroid Build Coastguard Worker   // Check we can disable instrumentation.
818*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
819*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
820*795d594fSAndroid Build Coastguard Worker }
821*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ConfigureStubs_InterpreterToInstrumentationStubs)822*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
823*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
824*795d594fSAndroid Build Coastguard Worker 
825*795d594fSAndroid Build Coastguard Worker   // Configure stubs with interpreter.
826*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
827*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
828*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
829*795d594fSAndroid Build Coastguard Worker 
830*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs.
831*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
832*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
833*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
834*795d594fSAndroid Build Coastguard Worker 
835*795d594fSAndroid Build Coastguard Worker   // Check we can disable instrumentation.
836*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
837*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
838*795d594fSAndroid Build Coastguard Worker }
839*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs)840*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest,
841*795d594fSAndroid Build Coastguard Worker        ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
842*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
843*795d594fSAndroid Build Coastguard Worker 
844*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs.
845*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
846*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
847*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
848*795d594fSAndroid Build Coastguard Worker 
849*795d594fSAndroid Build Coastguard Worker   // Configure stubs with interpreter.
850*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
851*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
852*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
853*795d594fSAndroid Build Coastguard Worker 
854*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs again.
855*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
856*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
857*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
858*795d594fSAndroid Build Coastguard Worker 
859*795d594fSAndroid Build Coastguard Worker   // Check we can disable instrumentation.
860*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
861*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
862*795d594fSAndroid Build Coastguard Worker }
863*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MultiConfigureStubs_Nothing)864*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
865*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
866*795d594fSAndroid Build Coastguard Worker 
867*795d594fSAndroid Build Coastguard Worker   // Check kInstrumentNothing with two clients.
868*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
869*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
870*795d594fSAndroid Build Coastguard Worker 
871*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
872*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
873*795d594fSAndroid Build Coastguard Worker }
874*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubs)875*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
876*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
877*795d594fSAndroid Build Coastguard Worker 
878*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs for 1st client.
879*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
880*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
881*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
882*795d594fSAndroid Build Coastguard Worker 
883*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs for 2nd client.
884*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey,
885*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
886*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 2U);
887*795d594fSAndroid Build Coastguard Worker 
888*795d594fSAndroid Build Coastguard Worker   // 1st client requests instrumentation deactivation but 2nd client still needs
889*795d594fSAndroid Build Coastguard Worker   // instrumentation stubs.
890*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
891*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
892*795d594fSAndroid Build Coastguard Worker 
893*795d594fSAndroid Build Coastguard Worker   // 2nd client requests instrumentation deactivation
894*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
895*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
896*795d594fSAndroid Build Coastguard Worker }
897*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MultiConfigureStubs_Interpreter)898*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
899*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
900*795d594fSAndroid Build Coastguard Worker 
901*795d594fSAndroid Build Coastguard Worker   // Configure stubs with interpreter for 1st client.
902*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
903*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
904*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
905*795d594fSAndroid Build Coastguard Worker 
906*795d594fSAndroid Build Coastguard Worker   // Configure stubs with interpreter for 2nd client.
907*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey,
908*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
909*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
910*795d594fSAndroid Build Coastguard Worker 
911*795d594fSAndroid Build Coastguard Worker   // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
912*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
913*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
914*795d594fSAndroid Build Coastguard Worker 
915*795d594fSAndroid Build Coastguard Worker   // 2nd client requests instrumentation deactivation
916*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
917*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
918*795d594fSAndroid Build Coastguard Worker }
919*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MultiConfigureStubs_InstrumentationStubsThenInterpreter)920*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
921*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
922*795d594fSAndroid Build Coastguard Worker 
923*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs for 1st client.
924*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
925*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
926*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
927*795d594fSAndroid Build Coastguard Worker 
928*795d594fSAndroid Build Coastguard Worker   // Configure stubs with interpreter for 2nd client.
929*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey,
930*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
931*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
932*795d594fSAndroid Build Coastguard Worker 
933*795d594fSAndroid Build Coastguard Worker   // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
934*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
935*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
936*795d594fSAndroid Build Coastguard Worker 
937*795d594fSAndroid Build Coastguard Worker   // 2nd client requests instrumentation deactivation
938*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
939*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
940*795d594fSAndroid Build Coastguard Worker }
941*795d594fSAndroid Build Coastguard Worker 
TEST_F(InstrumentationTest,MultiConfigureStubs_InterpreterThenInstrumentationStubs)942*795d594fSAndroid Build Coastguard Worker TEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
943*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
944*795d594fSAndroid Build Coastguard Worker 
945*795d594fSAndroid Build Coastguard Worker   // Configure stubs with interpreter for 1st client.
946*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey,
947*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
948*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
949*795d594fSAndroid Build Coastguard Worker 
950*795d594fSAndroid Build Coastguard Worker   // Configure stubs with instrumentation stubs for 2nd client.
951*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey,
952*795d594fSAndroid Build Coastguard Worker                       Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks);
953*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
954*795d594fSAndroid Build Coastguard Worker 
955*795d594fSAndroid Build Coastguard Worker   // 1st client requests instrumentation deactivation but 2nd client still needs
956*795d594fSAndroid Build Coastguard Worker   // instrumentation stubs.
957*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
958*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithEntryExitHooks, 1U);
959*795d594fSAndroid Build Coastguard Worker 
960*795d594fSAndroid Build Coastguard Worker   // 2nd client requests instrumentation deactivation
961*795d594fSAndroid Build Coastguard Worker   CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
962*795d594fSAndroid Build Coastguard Worker   CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
963*795d594fSAndroid Build Coastguard Worker }
964*795d594fSAndroid Build Coastguard Worker 
965*795d594fSAndroid Build Coastguard Worker }  // namespace instrumentation
966*795d594fSAndroid Build Coastguard Worker }  // namespace art
967