15eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz/*
25eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * Copyright (C) 2015 The Android Open Source Project
35eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz *
45eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * Licensed under the Apache License, Version 2.0 (the "License");
55eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * you may not use this file except in compliance with the License.
65eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * You may obtain a copy of the License at
75eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz *
85eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz *      http://www.apache.org/licenses/LICENSE-2.0
95eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz *
105eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * Unless required by applicable law or agreed to in writing, software
115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * distributed under the License is distributed on an "AS IS" BASIS,
125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * See the License for the specific language governing permissions and
145eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz * limitations under the License.
155eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz */
165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "instrumentation.h"
185eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
195eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "common_runtime_test.h"
205eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "common_throws.h"
215eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "class_linker-inl.h"
225eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "dex_file.h"
235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "handle_scope-inl.h"
245eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "jvalue.h"
255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "runtime.h"
265eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "scoped_thread_state_change.h"
275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "thread_list.h"
285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#include "thread-inl.h"
295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
305eae455507399286c845ba54796c47087a72b3e2Sebastien Hertznamespace art {
315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertznamespace instrumentation {
325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertzclass TestInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz public:
355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestInstrumentationListener()
365eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    : received_method_enter_event(false), received_method_exit_event(false),
375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      received_method_unwind_event(false), received_dex_pc_moved_event(false),
385eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      received_field_read_event(false), received_field_written_event(false),
395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      received_exception_caught_event(false), received_backward_branch_event(false) {}
405eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
415eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  virtual ~TestInstrumentationListener() {}
425eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
435eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                     mirror::Object* this_object ATTRIBUTE_UNUSED,
453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                     ArtMethod* method ATTRIBUTE_UNUSED,
465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                     uint32_t dex_pc ATTRIBUTE_UNUSED)
475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_method_enter_event = true;
495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
515eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    mirror::Object* this_object ATTRIBUTE_UNUSED,
533d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                    ArtMethod* method ATTRIBUTE_UNUSED,
545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    uint32_t dex_pc ATTRIBUTE_UNUSED,
555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    const JValue& return_value ATTRIBUTE_UNUSED)
565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
575eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_method_exit_event = true;
585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
605eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    mirror::Object* this_object ATTRIBUTE_UNUSED,
623d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                    ArtMethod* method ATTRIBUTE_UNUSED,
635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    uint32_t dex_pc ATTRIBUTE_UNUSED)
645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
655eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_method_unwind_event = true;
665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                  mirror::Object* this_object ATTRIBUTE_UNUSED,
703d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                  ArtMethod* method ATTRIBUTE_UNUSED,
715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                  uint32_t new_dex_pc ATTRIBUTE_UNUSED)
725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
735eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_dex_pc_moved_event = true;
745eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
775eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                 mirror::Object* this_object ATTRIBUTE_UNUSED,
783d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                 ArtMethod* method ATTRIBUTE_UNUSED,
795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                 uint32_t dex_pc ATTRIBUTE_UNUSED,
805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                 ArtField* field ATTRIBUTE_UNUSED)
815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_field_read_event = true;
835eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
845eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    mirror::Object* this_object ATTRIBUTE_UNUSED,
873d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                    ArtMethod* method ATTRIBUTE_UNUSED,
885eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    uint32_t dex_pc ATTRIBUTE_UNUSED,
895eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    ArtField* field ATTRIBUTE_UNUSED,
905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                    const JValue& field_value ATTRIBUTE_UNUSED)
915eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
925eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_field_written_event = true;
935eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
945eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
955eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED,
965eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                       mirror::Throwable* exception_object ATTRIBUTE_UNUSED)
975eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
985eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_exception_caught_event = true;
995eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
1005eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1015eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void BackwardBranch(Thread* thread ATTRIBUTE_UNUSED,
1023d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                      ArtMethod* method ATTRIBUTE_UNUSED,
1035eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      int32_t dex_pc_offset ATTRIBUTE_UNUSED)
1045eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1055eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_backward_branch_event = true;
1065eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
1075eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1085eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void Reset() {
1095eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_method_enter_event = false;
1105eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_method_exit_event = false;
1115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_method_unwind_event = false;
1125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_dex_pc_moved_event = false;
1135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_field_read_event = false;
1145eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_field_written_event = false;
1155eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_exception_caught_event = false;
1165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    received_backward_branch_event = false;
1175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
1185eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1195eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_method_enter_event;
1205eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_method_exit_event;
1215eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_method_unwind_event;
1225eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_dex_pc_moved_event;
1235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_field_read_event;
1245eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_field_written_event;
1255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_exception_caught_event;
1265eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  bool received_backward_branch_event;
1275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz private:
1295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  DISALLOW_COPY_AND_ASSIGN(TestInstrumentationListener);
1305eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz};
1315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertzclass InstrumentationTest : public CommonRuntimeTest {
1335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz public:
1345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Unique keys used to test Instrumentation::ConfigureStubs.
1355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  static constexpr const char* kClientOneKey = "TestClient1";
1365eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  static constexpr const char* kClientTwoKey = "TestClient2";
1375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1385eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void CheckConfigureStubs(const char* key, Instrumentation::InstrumentationLevel level) {
1395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    ScopedObjectAccess soa(Thread::Current());
1405eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
1415eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    {
1425eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
1435eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      Runtime* runtime = Runtime::Current();
1445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      runtime->GetThreadList()->SuspendAll("Instrumentation::ConfigureStubs");
1455eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      instr->ConfigureStubs(key, level);
1465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      runtime->GetThreadList()->ResumeAll();
1475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      soa.Self()->TransitionFromSuspendedToRunnable();
1485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
1495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
1505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1515eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Instrumentation::InstrumentationLevel GetCurrentInstrumentationLevel() {
1525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    return Runtime::Current()->GetInstrumentation()->GetCurrentInstrumentationLevel();
1535eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
1545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  size_t GetInstrumentationUserCount() {
1565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    ScopedObjectAccess soa(Thread::Current());
1575eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    return Runtime::Current()->GetInstrumentation()->requested_instrumentation_levels_.size();
1585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
1595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1605eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void TestEvent(uint32_t instrumentation_event) {
1615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    ScopedObjectAccess soa(Thread::Current());
1625eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
1635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    TestInstrumentationListener listener;
1645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    {
1655eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
1665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      Runtime* runtime = Runtime::Current();
1675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      runtime->GetThreadList()->SuspendAll("Add instrumentation listener");
1685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      instr->AddListener(&listener, instrumentation_event);
1695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      runtime->GetThreadList()->ResumeAll();
1705eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      soa.Self()->TransitionFromSuspendedToRunnable();
1715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
1725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1733d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ArtMethod* const event_method = nullptr;
1745eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    mirror::Object* const event_obj = nullptr;
1755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    const uint32_t event_dex_pc = 0;
1765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1775eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    // Check the listener is registered and is notified of the event.
1785eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_TRUE(HasEventListener(instr, instrumentation_event));
1795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
1805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
1815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_TRUE(DidListenerReceiveEvent(listener, instrumentation_event));
1825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1835eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    listener.Reset();
1845eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    {
1855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      soa.Self()->TransitionFromRunnableToSuspended(kSuspended);
1865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      Runtime* runtime = Runtime::Current();
1875eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      runtime->GetThreadList()->SuspendAll("Remove instrumentation listener");
1885eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      instr->RemoveListener(&listener, instrumentation_event);
1895eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      runtime->GetThreadList()->ResumeAll();
1905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      soa.Self()->TransitionFromSuspendedToRunnable();
1915eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
1925eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
1935eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    // Check the listener is not registered and is not notified of the event.
1945eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_FALSE(HasEventListener(instr, instrumentation_event));
1955eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
1965eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    ReportEvent(instr, instrumentation_event, soa.Self(), event_method, event_obj, event_dex_pc);
1975eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
1985eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
1995eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
2003d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
2015eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2025eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    Runtime* runtime = Runtime::Current();
2035eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
2045eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromRunnableToSuspended(kSuspended);
2055eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->SuspendAll("Single method deoptimization");
2065eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    if (enable_deoptimization) {
2075eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      instrumentation->EnableDeoptimization();
2085eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
2093d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    instrumentation->Deoptimize(method);
2105eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->ResumeAll();
2115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromSuspendedToRunnable();
2125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
2135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
2143d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  void UndeoptimizeMethod(Thread* self, ArtMethod* method,
2155eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                          const char* key, bool disable_deoptimization)
2165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    Runtime* runtime = Runtime::Current();
2185eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
2195eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromRunnableToSuspended(kSuspended);
2205eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->SuspendAll("Single method undeoptimization");
2213d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    instrumentation->Undeoptimize(method);
2225eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    if (disable_deoptimization) {
2235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      instrumentation->DisableDeoptimization(key);
2245eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
2255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->ResumeAll();
2265eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromSuspendedToRunnable();
2275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
2285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
2295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void DeoptimizeEverything(Thread* self, const char* key, bool enable_deoptimization)
2305eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    Runtime* runtime = Runtime::Current();
2325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
2335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromRunnableToSuspended(kSuspended);
2345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->SuspendAll("Full deoptimization");
2355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    if (enable_deoptimization) {
2365eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      instrumentation->EnableDeoptimization();
2375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
2385eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation->DeoptimizeEverything(key);
2395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->ResumeAll();
2405eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromSuspendedToRunnable();
2415eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
2425eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
2435eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void UndeoptimizeEverything(Thread* self, const char* key, bool disable_deoptimization)
2445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2455eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    Runtime* runtime = Runtime::Current();
2465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
2475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromRunnableToSuspended(kSuspended);
2485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->SuspendAll("Full undeoptimization");
2495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation->UndeoptimizeEverything(key);
2505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    if (disable_deoptimization) {
2515eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      instrumentation->DisableDeoptimization(key);
2525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
2535eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->ResumeAll();
2545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromSuspendedToRunnable();
2555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
2565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
2575eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void EnableMethodTracing(Thread* self, const char* key, bool needs_interpreter)
2585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    Runtime* runtime = Runtime::Current();
2605eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
2615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromRunnableToSuspended(kSuspended);
2625eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
2635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation->EnableMethodTracing(key, needs_interpreter);
2645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->ResumeAll();
2655eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromSuspendedToRunnable();
2665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
2675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
2685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  void DisableMethodTracing(Thread* self, const char* key)
2695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2705eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    Runtime* runtime = Runtime::Current();
2715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
2725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromRunnableToSuspended(kSuspended);
2735eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->SuspendAll("EnableMethodTracing");
2745eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    instrumentation->DisableMethodTracing(key);
2755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    runtime->GetThreadList()->ResumeAll();
2765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    self->TransitionFromSuspendedToRunnable();
2775eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
2785eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
2795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz private:
2805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  static bool HasEventListener(const instrumentation::Instrumentation* instr, uint32_t event_type)
2815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    switch (event_type) {
2835eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodEntered:
2845eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasMethodEntryListeners();
2855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodExited:
2865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasMethodExitListeners();
2875eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodUnwind:
2885eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasMethodUnwindListeners();
2895eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kDexPcMoved:
2905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasDexPcListeners();
2915eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kFieldRead:
2925eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasFieldReadListeners();
2935eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kFieldWritten:
2945eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasFieldWriteListeners();
2955eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kExceptionCaught:
2965eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasExceptionCaughtListeners();
2975eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kBackwardBranch:
2985eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return instr->HasBackwardBranchListeners();
2995eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      default:
3005eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        LOG(FATAL) << "Unknown instrumentation event " << event_type;
3015eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        UNREACHABLE();
3025eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
3035eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
3045eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
3055eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
3063d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                          Thread* self, ArtMethod* method, mirror::Object* obj,
3075eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                          uint32_t dex_pc)
3085eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3095eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    switch (event_type) {
3105eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodEntered:
3115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->MethodEnterEvent(self, obj, method, dex_pc);
3125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodExited: {
3145eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        JValue value;
3155eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->MethodExitEvent(self, obj, method, dex_pc, value);
3165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      }
3185eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodUnwind:
3195eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->MethodUnwindEvent(self, obj, method, dex_pc);
3205eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3215eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kDexPcMoved:
3225eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->DexPcMovedEvent(self, obj, method, dex_pc);
3235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3245eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kFieldRead:
3255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->FieldReadEvent(self, obj, method, dex_pc, nullptr);
3265eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kFieldWritten: {
3285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        JValue value;
3295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->FieldWriteEvent(self, obj, method, dex_pc, nullptr, value);
3305eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      }
3325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kExceptionCaught: {
3335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        ThrowArithmeticExceptionDivideByZero();
3345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        mirror::Throwable* event_exception = self->GetException();
3355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->ExceptionCaughtEvent(self, event_exception);
3365eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        self->ClearException();
3375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3385eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      }
3395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kBackwardBranch:
3405eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        instr->BackwardBranch(self, method, dex_pc);
3415eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        break;
3425eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      default:
3435eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        LOG(FATAL) << "Unknown instrumentation event " << event_type;
3445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        UNREACHABLE();
3455eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
3465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
3475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
3485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  static bool DidListenerReceiveEvent(const TestInstrumentationListener& listener,
3495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                                      uint32_t event_type) {
3505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    switch (event_type) {
3515eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodEntered:
3525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_method_enter_event;
3535eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodExited:
3545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_method_exit_event;
3555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kMethodUnwind:
3565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_method_unwind_event;
3575eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kDexPcMoved:
3585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_dex_pc_moved_event;
3595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kFieldRead:
3605eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_field_read_event;
3615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kFieldWritten:
3625eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_field_written_event;
3635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kExceptionCaught:
3645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_exception_caught_event;
3655eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      case instrumentation::Instrumentation::kBackwardBranch:
3665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        return listener.received_backward_branch_event;
3675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      default:
3685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        LOG(FATAL) << "Unknown instrumentation event " << event_type;
3695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz        UNREACHABLE();
3705eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }
3715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  }
3725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz};
3735eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
3745eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, NoInstrumentation) {
3755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ScopedObjectAccess soa(Thread::Current());
3765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
3775eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ASSERT_NE(instr, nullptr);
3785eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
3795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreExitStubsInstalled());
3805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
3815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->IsActive());
3825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->ShouldNotifyMethodEnterExitEvents());
3835eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
3845eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Test interpreter table is the default one.
3855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(instrumentation::kMainHandlerTable, instr->GetInterpreterHandlerTable());
3865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
3875eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check there is no registered listener.
3885eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->HasDexPcListeners());
3895eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->HasExceptionCaughtListeners());
3905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->HasFieldReadListeners());
3915eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->HasFieldWriteListeners());
3925eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->HasMethodEntryListeners());
3935eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->HasMethodExitListeners());
3945eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->IsActive());
3955eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
3965eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
3975eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz// Test instrumentation listeners for each event.
3985eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MethodEntryEvent) {
3995eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kMethodEntered);
4005eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4015eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4025eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MethodExitEvent) {
4035eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kMethodExited);
4045eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4055eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4065eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MethodUnwindEvent) {
4075eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kMethodUnwind);
4085eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4095eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4105eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, DexPcMovedEvent) {
4115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kDexPcMoved);
4125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4145eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, FieldReadEvent) {
4155eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kFieldRead);
4165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4185eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, FieldWriteEvent) {
4195eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kFieldWritten);
4205eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4215eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4225eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, ExceptionCaughtEvent) {
4235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kExceptionCaught);
4245eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4265eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, BackwardBranchEvent) {
4275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  TestEvent(instrumentation::Instrumentation::kBackwardBranch);
4285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4305eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, DeoptimizeDirectMethod) {
4315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ScopedObjectAccess soa(Thread::Current());
4325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  jobject class_loader = LoadDex("Instrumentation");
4335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Runtime* const runtime = Runtime::Current();
4345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
4355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ClassLinker* class_linker = runtime->GetClassLinker();
4363d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  StackHandleScope<1> hs(soa.Self());
4375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
4385eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
4395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ASSERT_TRUE(klass != nullptr);
4403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
4413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                                                                    sizeof(void*));
4423d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ASSERT_TRUE(method_to_deoptimize != nullptr);
4435eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
4453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
4465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
4485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
4505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreExitStubsInstalled());
4513d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
4525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4535eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
4545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
4555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
4573d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
4585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4605eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, FullDeoptimization) {
4615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ScopedObjectAccess soa(Thread::Current());
4625eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Runtime* const runtime = Runtime::Current();
4635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
4645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
4655eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  constexpr const char* instrumentation_key = "FullDeoptimization";
4675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  DeoptimizeEverything(soa.Self(), instrumentation_key, true);
4685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
4705eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreExitStubsInstalled());
4715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  UndeoptimizeEverything(soa.Self(), instrumentation_key, true);
4735eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4745eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
4755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
4765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4775eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MixedDeoptimization) {
4785eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ScopedObjectAccess soa(Thread::Current());
4795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  jobject class_loader = LoadDex("Instrumentation");
4805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Runtime* const runtime = Runtime::Current();
4815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
4825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ClassLinker* class_linker = runtime->GetClassLinker();
4833d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  StackHandleScope<1> hs(soa.Self());
4845eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
4855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
4865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ASSERT_TRUE(klass != nullptr);
4873d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
4883d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                                                                    sizeof(void*));
4893d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ASSERT_TRUE(method_to_deoptimize != nullptr);
4905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4915eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
4923d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
4935eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
4945eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
4955eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Deoptimizing a method does not change instrumentation level.
4965eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
4975eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
4985eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
4995eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreExitStubsInstalled());
5003d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
5015eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5025eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  constexpr const char* instrumentation_key = "MixedDeoptimization";
5035eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  DeoptimizeEverything(soa.Self(), instrumentation_key, false);
5045eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
5055eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
5065eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
5075eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreExitStubsInstalled());
5083d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
5095eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5105eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
5115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
5125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
5135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
5145eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreExitStubsInstalled());
5153d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
5165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
5185eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
5195eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
5205eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
5213d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
5225eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
5235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5245eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MethodTracing_Interpreter) {
5255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ScopedObjectAccess soa(Thread::Current());
5265eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Runtime* const runtime = Runtime::Current();
5275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
5285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
5295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5305eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  constexpr const char* instrumentation_key = "MethodTracing";
5315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EnableMethodTracing(soa.Self(), instrumentation_key, true);
5325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter,
5335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
5345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
5355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreExitStubsInstalled());
5365eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  DisableMethodTracing(soa.Self(), instrumentation_key);
5385eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
5395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
5405eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
5415eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
5425eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5435eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MethodTracing_InstrumentationEntryExitStubs) {
5445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  ScopedObjectAccess soa(Thread::Current());
5455eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  Runtime* const runtime = Runtime::Current();
5465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
5475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
5485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  constexpr const char* instrumentation_key = "MethodTracing";
5505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EnableMethodTracing(soa.Self(), instrumentation_key, false);
5515eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
5525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
5535eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
5545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_TRUE(instr->AreExitStubsInstalled());
5555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  DisableMethodTracing(soa.Self(), instrumentation_key);
5575eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
5585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz            GetCurrentInstrumentationLevel());
5595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
5605eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
5615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5625eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz// We use a macro to print the line number where the test is failing.
5635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz#define CHECK_INSTRUMENTATION(_level, _user_count)                                      \
5645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  do {                                                                                  \
5655eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    Instrumentation* const instr = Runtime::Current()->GetInstrumentation();            \
5665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    bool interpreter =                                                                  \
5675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      (_level == Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);    \
5685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_EQ(_level, GetCurrentInstrumentationLevel());                                \
5695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    EXPECT_EQ(_user_count, GetInstrumentationUserCount());                              \
5705eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    if (instr->IsForcedInterpretOnly()) {                                               \
5715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      EXPECT_TRUE(instr->InterpretOnly());                                              \
5725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    } else if (interpreter) {                                                           \
5735eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      EXPECT_TRUE(instr->InterpretOnly());                                              \
5745eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    } else {                                                                            \
5755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      EXPECT_FALSE(instr->InterpretOnly());                                             \
5765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }                                                                                   \
5775eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    if (interpreter) {                                                                  \
5785eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      EXPECT_TRUE(instr->AreAllMethodsDeoptimized());                                   \
5795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    } else {                                                                            \
5805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz      EXPECT_FALSE(instr->AreAllMethodsDeoptimized());                                  \
5815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz    }                                                                                   \
5825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  } while (false)
5835eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5845eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, ConfigureStubs_Nothing) {
5855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
5865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5875eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check no-op.
5885eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
5895eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
5905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
5915eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5925eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubs) {
5935eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
5945eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
5955eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check we can switch to instrumentation stubs
5965eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
5975eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
5985eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
5995eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
6005eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6015eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check we can disable instrumentation.
6025eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
6035eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6045eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
6055eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6065eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, ConfigureStubs_Interpreter) {
6075eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6085eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6095eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check we can switch to interpreter
6105eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
6125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
6135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6145eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check we can disable instrumentation.
6155eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
6165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
6185eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6195eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, ConfigureStubs_InstrumentationStubsToInterpreter) {
6205eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6215eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6225eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs.
6235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6245eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
6255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
6265eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
6275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with interpreter.
6295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6305eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
6315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
6325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check we can disable instrumentation.
6345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
6355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6365eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
6375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6385eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, ConfigureStubs_InterpreterToInstrumentationStubs) {
6395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6405eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6415eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with interpreter.
6425eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6435eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
6445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
6455eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs.
6475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
6495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
6505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
6515eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check we can disable instrumentation.
6535eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
6545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
6565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6575eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest,
6585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz       ConfigureStubs_InstrumentationStubsToInterpreterToInstrumentationStubs) {
6595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6605eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs.
6625eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
6645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
6655eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
6665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with interpreter.
6685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
6705eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
6715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs again.
6735eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6745eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
6755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
6765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
6775eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6785eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check we can disable instrumentation.
6795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
6805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
6825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6835eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MultiConfigureStubs_Nothing) {
6845eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Check kInstrumentNothing with two clients.
6875eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
6885eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6895eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
6915eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6925eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
6935eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6945eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubs) {
6955eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
6965eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
6975eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs for 1st client.
6985eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
6995eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
7005eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
7015eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
7025eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7035eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs for 2nd client.
7045eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey,
7055eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
7065eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
7075eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        2U);
7085eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7095eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 1st client requests instrumentation deactivation but 2nd client still needs
7105eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // instrumentation stubs.
7115eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7125eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
7135eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
7145eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7155eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 2nd client requests instrumentation deactivation
7165eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7175eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
7185eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
7195eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7205eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MultiConfigureStubs_Interpreter) {
7215eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
7225eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7235eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with interpreter for 1st client.
7245eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
7255eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
7265eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
7275eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7285eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with interpreter for 2nd client.
7295eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey,
7305eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
7315eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
7325eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7335eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
7345eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7355eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
7365eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7375eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 2nd client requests instrumentation deactivation
7385eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7395eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
7405eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
7415eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7425eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MultiConfigureStubs_InstrumentationStubsThenInterpreter) {
7435eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
7445eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7455eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs for 1st client.
7465eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
7475eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
7485eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
7495eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
7505eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7515eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with interpreter for 2nd client.
7525eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey,
7535eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
7545eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
7555eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7565eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 1st client requests instrumentation deactivation but 2nd client still needs interpreter.
7575eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7585eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
7595eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7605eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 2nd client requests instrumentation deactivation
7615eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7625eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
7635eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
7645eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7655eae455507399286c845ba54796c47087a72b3e2Sebastien HertzTEST_F(InstrumentationTest, MultiConfigureStubs_InterpreterThenInstrumentationStubs) {
7665eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
7675eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7685eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with interpreter for 1st client.
7695eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey,
7705eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter);
7715eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 1U);
7725eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7735eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // Configure stubs with instrumentation stubs for 2nd client.
7745eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey,
7755eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                      Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs);
7765eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter, 2U);
7775eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7785eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 1st client requests instrumentation deactivation but 2nd client still needs
7795eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // instrumentation stubs.
7805eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientOneKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7815eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentWithInstrumentationStubs,
7825eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz                        1U);
7835eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7845eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  // 2nd client requests instrumentation deactivation
7855eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CheckConfigureStubs(kClientTwoKey, Instrumentation::InstrumentationLevel::kInstrumentNothing);
7865eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz  CHECK_INSTRUMENTATION(Instrumentation::InstrumentationLevel::kInstrumentNothing, 0U);
7875eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}
7885eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz
7895eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}  // namespace instrumentation
7905eae455507399286c845ba54796c47087a72b3e2Sebastien Hertz}  // namespace art
791