instrumentation.h revision ed2be1725fb79075892b1a9103487c9d9a95b350
1725a957985171d712d5c048cc3d00ff14968784bjeffhao/*
2725a957985171d712d5c048cc3d00ff14968784bjeffhao * Copyright (C) 2011 The Android Open Source Project
3725a957985171d712d5c048cc3d00ff14968784bjeffhao *
4725a957985171d712d5c048cc3d00ff14968784bjeffhao * Licensed under the Apache License, Version 2.0 (the "License");
5725a957985171d712d5c048cc3d00ff14968784bjeffhao * you may not use this file except in compliance with the License.
6725a957985171d712d5c048cc3d00ff14968784bjeffhao * You may obtain a copy of the License at
7725a957985171d712d5c048cc3d00ff14968784bjeffhao *
8725a957985171d712d5c048cc3d00ff14968784bjeffhao *      http://www.apache.org/licenses/LICENSE-2.0
9725a957985171d712d5c048cc3d00ff14968784bjeffhao *
10725a957985171d712d5c048cc3d00ff14968784bjeffhao * Unless required by applicable law or agreed to in writing, software
11725a957985171d712d5c048cc3d00ff14968784bjeffhao * distributed under the License is distributed on an "AS IS" BASIS,
12725a957985171d712d5c048cc3d00ff14968784bjeffhao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13725a957985171d712d5c048cc3d00ff14968784bjeffhao * See the License for the specific language governing permissions and
14725a957985171d712d5c048cc3d00ff14968784bjeffhao * limitations under the License.
15725a957985171d712d5c048cc3d00ff14968784bjeffhao */
16725a957985171d712d5c048cc3d00ff14968784bjeffhao
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_INSTRUMENTATION_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_INSTRUMENTATION_H_
19725a957985171d712d5c048cc3d00ff14968784bjeffhao
20576ca0cd692c0b6ae70e776de91015b8ff000a08Ian Rogers#include <stdint.h>
21576ca0cd692c0b6ae70e776de91015b8ff000a08Ian Rogers#include <list>
22799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi#include <map>
23576ca0cd692c0b6ae70e776de91015b8ff000a08Ian Rogers
24ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "atomic.h"
25d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe#include "instruction_set.h"
26761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
27719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers#include "base/mutex.h"
2894f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi#include "gc_root.h"
293b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier#include "object_callbacks.h"
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
31725a957985171d712d5c048cc3d00ff14968784bjeffhaonamespace art {
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace mirror {
333f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  class ArtField;
34ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class ArtMethod;
35ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Class;
36ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Object;
37ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Throwable;
3862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}  // namespace mirror
3962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersunion JValue;
40725a957985171d712d5c048cc3d00ff14968784bjeffhaoclass Thread;
4162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersclass ThrowLocation;
42725a957985171d712d5c048cc3d00ff14968784bjeffhao
4362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersnamespace instrumentation {
44725a957985171d712d5c048cc3d00ff14968784bjeffhao
45ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz// Interpreter handler tables.
46ee1997a3b83334985e757f369c09e111b121661bSebastien Hertzenum InterpreterHandlerTable {
47ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  kMainHandlerTable = 0,          // Main handler table: no suspend check, no instrumentation.
48ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  kAlternativeHandlerTable = 1,   // Alternative handler table: suspend check and/or instrumentation
49ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz                                  // enabled.
50ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  kNumHandlerTables
51ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz};
52ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
5362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// Instrumentation event listener API. Registered listeners will get the appropriate call back for
5462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// the events they are listening for. The call backs supply the thread, method and dex_pc the event
5562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// occurred upon. The thread may or may not be Thread::Current().
5662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstruct InstrumentationListener {
5762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  InstrumentationListener() {}
5862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual ~InstrumentationListener() {}
5962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
6062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is entered.
6162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
62ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                             mirror::ArtMethod* method,
6362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                             uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
6462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
6562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is exited.
6662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // TODO: its likely passing the return value would be useful, however, we may need to get and
6762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  //       parse the shorty to determine what kind of register holds the result.
6862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void MethodExited(Thread* thread, mirror::Object* this_object,
69ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                            mirror::ArtMethod* method, uint32_t dex_pc,
7062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            const JValue& return_value)
7162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
7262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is popped due to an exception throw. A method will either cause a
7462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // MethodExited call-back or a MethodUnwind call-back when its activation is removed.
7551db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz  virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
76ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                            mirror::ArtMethod* method, uint32_t dex_pc)
7751db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
7862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when the dex pc moves in a method.
8062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
81ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                          mirror::ArtMethod* method, uint32_t new_dex_pc)
8262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
8362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
843f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // Call-back for when we read from a field.
853f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  virtual void FieldRead(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
863f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                         uint32_t dex_pc, mirror::ArtField* field) = 0;
873f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
883f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // Call-back for when we write into a field.
893f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  virtual void FieldWritten(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
903f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                            uint32_t dex_pc, mirror::ArtField* field, const JValue& field_value) = 0;
913f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
9262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back when an exception is caught.
9362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
94ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                               mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
9562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                               mirror::Throwable* exception_object)
9662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
97725a957985171d712d5c048cc3d00ff14968784bjeffhao};
98725a957985171d712d5c048cc3d00ff14968784bjeffhao
9962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// Instrumentation is a catch-all for when extra information is required from the runtime. The
10062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// typical use for instrumentation is for profiling and debugging. Instrumentation may add stubs
10162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// to method entry and exit, it may also force execution to be switched to the interpreter and
10262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// trigger deoptimization.
103725a957985171d712d5c048cc3d00ff14968784bjeffhaoclass Instrumentation {
104725a957985171d712d5c048cc3d00ff14968784bjeffhao public:
10562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  enum InstrumentationEvent {
1063f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    kMethodEntered =   1 << 0,
1073f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    kMethodExited =    1 << 1,
1083f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    kMethodUnwind =    1 << 2,
1093f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    kDexPcMoved =      1 << 3,
1103f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    kFieldRead =       1 << 4,
1113f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    kFieldWritten =    1 << 5,
1123f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    kExceptionCaught = 1 << 6,
11362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  };
11462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
1153b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  Instrumentation();
11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
11762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Add a listener to be notified of the masked together sent of instrumentation events. This
11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // suspend the runtime to install stubs. You are expected to hold the mutator lock as a proxy
11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // for saying you should have suspended all threads (installing stubs while threads are running
12062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // will break).
12162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void AddListener(InstrumentationListener* listener, uint32_t events)
12262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
12362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
12462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
12562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Removes a listener possibly removing instrumentation stubs.
12662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void RemoveListener(InstrumentationListener* listener, uint32_t events)
12762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
12862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
12962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
130138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Deoptimization.
131a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  void EnableDeoptimization()
132a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
1333b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(deoptimized_methods_lock_);
134a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  void DisableDeoptimization()
135a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
1364d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      LOCKS_EXCLUDED(deoptimized_methods_lock_);
137a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  bool AreAllMethodsDeoptimized() const {
138a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz    return interpreter_stubs_installed_;
139a76a6d4cb3dedec909bd927f20bc0ab23198a337Sebastien Hertz  }
14011d40c250ec86c784cf76b8c31e1cf9285d555dcSebastien Hertz  bool ShouldNotifyMethodEnterExitEvents() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
141138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
142138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Executes everything with interpreter.
143138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void DeoptimizeEverything()
144138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
145138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
146138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
147138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Executes everything with compiled code (or interpreter if there is no code).
148138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void UndeoptimizeEverything()
149138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
150138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
151138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
152138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Deoptimize a method by forcing its execution with the interpreter. Nevertheless, a static
153138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // method (except a class initializer) set to the resolution trampoline will be deoptimized only
154138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // once its declaring class is initialized.
155138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void Deoptimize(mirror::ArtMethod* method)
1563b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(Locks::thread_list_lock_, deoptimized_methods_lock_)
157138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
158138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
159138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Undeoptimze the method by restoring its entrypoints. Nevertheless, a static method
160138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // (except a class initializer) set to the resolution trampoline will be updated only once its
161138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // declaring class is initialized.
162138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void Undeoptimize(mirror::ArtMethod* method)
1634d25df3f76f864b7629ac8c0046d46997f293d8dSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, deoptimized_methods_lock_)
164138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
165138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
166799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi  bool IsDeoptimized(mirror::ArtMethod* method)
167799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      LOCKS_EXCLUDED(deoptimized_methods_lock_)
168799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
169138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
170138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Enable method tracing by installing instrumentation entry/exit stubs.
171138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void EnableMethodTracing()
172138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
173138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
174138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
175138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Disable method tracing by uninstalling instrumentation entry/exit stubs.
176138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void DisableMethodTracing()
177138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
178138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
179138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
180ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  InterpreterHandlerTable GetInterpreterHandlerTable() const
181ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
182ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz    return interpreter_handler_table_;
183ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  }
184ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
185d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier  void InstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_,
186d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier                                                        Locks::runtime_shutdown_lock_);
187d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier  void UninstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_,
188d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier                                                          Locks::runtime_shutdown_lock_);
189d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier  void ResetQuickAllocEntryPoints() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
190fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers
19162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Update the code of a method respecting any installed stubs.
192ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code,
193799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi                         const void* portable_code, bool have_portable_code)
194138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
19562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
19662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Get the quick code for the given method. More efficient than asking the class linker as it
19762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // will short-cut to GetCode if instrumentation and static method resolution stubs aren't
19862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // installed.
199ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetQuickCodeFor(mirror::ArtMethod* method) const
20062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
20262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ForceInterpretOnly() {
20362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    interpret_only_ = true;
20462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    forced_interpret_only_ = true;
20562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
20662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
207ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Called by ArtMethod::Invoke to determine dispatch mechanism.
20862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool InterpretOnly() const {
20962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return interpret_only_;
21062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
21162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
212563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi  bool IsForcedInterpretOnly() const {
213563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi    return forced_interpret_only_;
214563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi  }
215563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi
21662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool ShouldPortableCodeDeoptimize() const {
21762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return instrumentation_stubs_installed_;
21862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
21962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
22062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool AreExitStubsInstalled() const {
22162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return instrumentation_stubs_installed_;
22262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
22362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
224ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool HasMethodEntryListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
22574109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_method_entry_listeners_;
22674109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
22774109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
228ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool HasMethodExitListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
22974109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_method_exit_listeners_;
23074109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
23174109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
232ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool HasDexPcListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
23374109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_dex_pc_listeners_;
23474109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
23574109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
236ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool HasFieldReadListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2373f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    return have_field_read_listeners_;
2383f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
2393f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
240ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool HasFieldWriteListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2413f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    return have_field_write_listeners_;
2423f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
2433f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
244ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool HasExceptionCaughtListeners() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2459f1020305292a21fd14a402b189c765a125226abSebastien Hertz    return have_exception_caught_listeners_;
2469f1020305292a21fd14a402b189c765a125226abSebastien Hertz  }
2479f1020305292a21fd14a402b189c765a125226abSebastien Hertz
248ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool IsActive() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
249ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz    return have_dex_pc_listeners_ || have_method_entry_listeners_ || have_method_exit_listeners_ ||
25042cd43fa593e8f0427eb0ec158bef08814a6180bSebastien Hertz        have_field_read_listeners_ || have_field_write_listeners_ ||
251ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz        have_exception_caught_listeners_ || have_method_unwind_listeners_;
252ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  }
253ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
25462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been entered. A dex PC is provided as we may install
25562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // listeners into executing code and get method enter events for methods already on the stack.
25662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodEnterEvent(Thread* thread, mirror::Object* this_object,
257ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                        mirror::ArtMethod* method, uint32_t dex_pc) const
25862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
25974109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasMethodEntryListeners())) {
26062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      MethodEnterEventImpl(thread, this_object, method, dex_pc);
26162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
26262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
26362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
26462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been exited.
26562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodExitEvent(Thread* thread, mirror::Object* this_object,
266ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                       mirror::ArtMethod* method, uint32_t dex_pc,
26762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                       const JValue& return_value) const
26862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
26974109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasMethodExitListeners())) {
27062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      MethodExitEventImpl(thread, this_object, method, dex_pc, return_value);
27162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
27262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
27362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
27462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been exited due to an exception.
27562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
276ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                         mirror::ArtMethod* method, uint32_t dex_pc) const
27762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
27862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
27962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that the dex pc has moved (only supported by the interpreter).
28062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void DexPcMovedEvent(Thread* thread, mirror::Object* this_object,
281ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                       mirror::ArtMethod* method, uint32_t dex_pc) const
28262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
28374109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasDexPcListeners())) {
28462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      DexPcMovedEventImpl(thread, this_object, method, dex_pc);
28562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
28662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
287725a957985171d712d5c048cc3d00ff14968784bjeffhao
2883f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // Inform listeners that we read a field (only supported by the interpreter).
2893f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  void FieldReadEvent(Thread* thread, mirror::Object* this_object,
2903f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                      mirror::ArtMethod* method, uint32_t dex_pc,
2913f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                      mirror::ArtField* field) const
2923f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
2933f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    if (UNLIKELY(HasFieldReadListeners())) {
2943f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz      FieldReadEventImpl(thread, this_object, method, dex_pc, field);
2953f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    }
2963f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
2973f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
2983f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // Inform listeners that we write a field (only supported by the interpreter).
2993f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  void FieldWriteEvent(Thread* thread, mirror::Object* this_object,
3003f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                       mirror::ArtMethod* method, uint32_t dex_pc,
3013f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                       mirror::ArtField* field, const JValue& field_value) const
3023f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3033f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    if (UNLIKELY(HasFieldWriteListeners())) {
3043f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz      FieldWriteEventImpl(thread, this_object, method, dex_pc, field, field_value);
3053f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz    }
3063f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  }
3073f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
30862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that an exception was caught.
30962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ExceptionCaughtEvent(Thread* thread, const ThrowLocation& throw_location,
310ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                            mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
311947ff080753c786a74f1cd7aeb09f717bb7074bdSebastien Hertz                            mirror::Throwable* exception_object) const
31262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
313725a957985171d712d5c048cc3d00ff14968784bjeffhao
31462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Called when an instrumented method is entered. The intended link register (lr) is saved so
31562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // that returning causes a branch to the method exit stub. Generates method enter events.
31662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void PushInstrumentationStackFrame(Thread* self, mirror::Object* this_object,
317ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                     mirror::ArtMethod* method, uintptr_t lr,
3189a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao                                     bool interpreter_entry)
31962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
320725a957985171d712d5c048cc3d00ff14968784bjeffhao
32162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Called when an instrumented method is exited. Removes the pushed instrumentation frame
32262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // returning the intended link register. Generates method exit events.
323d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe  TwoWordReturn PopInstrumentationStackFrame(Thread* self, uintptr_t* return_pc,
324d58342caa97108ba413bad467c285c0377f138f5Andreas Gampe                                             uint64_t gpr_result, uint64_t fpr_result)
32562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
326725a957985171d712d5c048cc3d00ff14968784bjeffhao
32762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Pops an instrumentation frame from the current thread and generate an unwind event.
32862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void PopMethodForUnwind(Thread* self, bool is_deoptimization) const
32962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
33062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
33162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call back for configure stubs.
33262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool InstallStubsForClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
333725a957985171d712d5c048cc3d00ff14968784bjeffhao
334138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void InstallStubsForMethod(mirror::ArtMethod* method)
335138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
336138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
3373b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
3383b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(deoptimized_methods_lock_);
3393b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier
340725a957985171d712d5c048cc3d00ff14968784bjeffhao private:
34162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Does the job of installing or removing instrumentation code within methods.
34262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ConfigureStubs(bool require_entry_exit_stubs, bool require_interpreter)
34362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
3443b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_,
3453b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier                     deoptimized_methods_lock_);
34662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
347ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  void UpdateInterpreterHandlerTable() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
348ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz    interpreter_handler_table_ = IsActive() ? kAlternativeHandlerTable : kMainHandlerTable;
349ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  }
350ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
351661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  // No thread safety analysis to get around SetQuickAllocEntryPointsInstrumented requiring
352661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  // exclusive access to mutator lock which you can't get if the runtime isn't started.
353661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  void SetEntrypointsInstrumented(bool instrumented) NO_THREAD_SAFETY_ANALYSIS;
354661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier
35562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
356ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                            mirror::ArtMethod* method, uint32_t dex_pc) const
35762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
35862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
359ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                           mirror::ArtMethod* method,
36062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                           uint32_t dex_pc, const JValue& return_value) const
36162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
36262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
363ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                           mirror::ArtMethod* method, uint32_t dex_pc) const
36462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
3653f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  void FieldReadEventImpl(Thread* thread, mirror::Object* this_object,
3663f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                           mirror::ArtMethod* method, uint32_t dex_pc,
3673f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                           mirror::ArtField* field) const
3683f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
3693f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  void FieldWriteEventImpl(Thread* thread, mirror::Object* this_object,
3703f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                           mirror::ArtMethod* method, uint32_t dex_pc,
3713f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz                           mirror::ArtField* field, const JValue& field_value) const
3723f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
37362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
374799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi  // Read barrier-aware utility functions for accessing deoptimized_methods_
375799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi  bool AddDeoptimizedMethod(mirror::ArtMethod* method)
376799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
377799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      EXCLUSIVE_LOCKS_REQUIRED(deoptimized_methods_lock_);
378799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi  bool FindDeoptimizedMethod(mirror::ArtMethod* method)
379799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
380799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(deoptimized_methods_lock_);
381799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi  bool RemoveDeoptimizedMethod(mirror::ArtMethod* method)
382799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
383799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      EXCLUSIVE_LOCKS_REQUIRED(deoptimized_methods_lock_);
384799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi  mirror::ArtMethod* BeginDeoptimizedMethod()
385799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
386799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(deoptimized_methods_lock_);
387799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi  bool IsDeoptimizedMethodsEmpty() const
388799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
389799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi      SHARED_LOCKS_REQUIRED(deoptimized_methods_lock_);
390799eb3a5555254427db269921042419bc30d4d86Hiroshi Yamauchi
391ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ so that it calls instrumentation/interpreter code?
39262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool instrumentation_stubs_installed_;
39362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
394ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ to reference the enter/exit stubs?
39562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool entry_exit_stubs_installed_;
39662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
397ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ to reference the enter interpreter stub?
39862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool interpreter_stubs_installed_;
39962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
40062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we need the fidelity of events that we only get from running within the interpreter?
40162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool interpret_only_;
402725a957985171d712d5c048cc3d00ff14968784bjeffhao
40362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Did the runtime request we only run in the interpreter? ie -Xint mode.
40462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool forced_interpret_only_;
405725a957985171d712d5c048cc3d00ff14968784bjeffhao
40662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method entry events? Short-cut to avoid taking the
40762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
408ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool have_method_entry_listeners_ GUARDED_BY(Locks::mutator_lock_);
40962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
41062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method exit events? Short-cut to avoid taking the
41162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
412ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool have_method_exit_listeners_ GUARDED_BY(Locks::mutator_lock_);
41362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
41462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method unwind events? Short-cut to avoid taking the
41562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
416ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool have_method_unwind_listeners_ GUARDED_BY(Locks::mutator_lock_);
41762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
41862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for dex move events? Short-cut to avoid taking the
41962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
420ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool have_dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
42162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
4223f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // Do we have any listeners for field read events? Short-cut to avoid taking the
4233f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // instrumentation_lock_.
424ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool have_field_read_listeners_ GUARDED_BY(Locks::mutator_lock_);
4253f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
4263f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // Do we have any listeners for field write events? Short-cut to avoid taking the
4273f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz  // instrumentation_lock_.
428ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool have_field_write_listeners_ GUARDED_BY(Locks::mutator_lock_);
4293f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz
43062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any exception caught listeners? Short-cut to avoid taking the instrumentation_lock_.
431ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  bool have_exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
43262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
43362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // The event listeners, written to with the mutator_lock_ exclusively held.
43462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_entry_listeners_ GUARDED_BY(Locks::mutator_lock_);
43562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_exit_listeners_ GUARDED_BY(Locks::mutator_lock_);
43662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_unwind_listeners_ GUARDED_BY(Locks::mutator_lock_);
437ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi  std::shared_ptr<std::list<InstrumentationListener*>> dex_pc_listeners_
438ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi      GUARDED_BY(Locks::mutator_lock_);
439ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi  std::shared_ptr<std::list<InstrumentationListener*>> field_read_listeners_
440ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi      GUARDED_BY(Locks::mutator_lock_);
441ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi  std::shared_ptr<std::list<InstrumentationListener*>> field_write_listeners_
442ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi      GUARDED_BY(Locks::mutator_lock_);
443ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi  std::shared_ptr<std::list<InstrumentationListener*>> exception_caught_listeners_
444ca1d06cfa2f2b8d2be4390644e126cb68cdbb5baDaniel Mihalyi      GUARDED_BY(Locks::mutator_lock_);
445725a957985171d712d5c048cc3d00ff14968784bjeffhao
446138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // The set of methods being deoptimized (by the debugger) which must be executed with interpreter
447138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // only.
4483b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  mutable ReaderWriterMutex deoptimized_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
44994f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi  std::multimap<int32_t, GcRoot<mirror::ArtMethod>> deoptimized_methods_
45094f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi      GUARDED_BY(deoptimized_methods_lock_);
45111d40c250ec86c784cf76b8c31e1cf9285d555dcSebastien Hertz  bool deoptimization_enabled_;
452138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
453fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // Current interpreter handler table. This is updated each time the thread state flags are
454fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // modified.
455ed2be1725fb79075892b1a9103487c9d9a95b350Sebastien Hertz  InterpreterHandlerTable interpreter_handler_table_ GUARDED_BY(Locks::mutator_lock_);
456ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
457fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // Greater than 0 if quick alloc entry points instrumented.
458fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // TODO: The access and changes to this is racy and should be guarded by a lock.
459cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier  AtomicInteger quick_alloc_entry_points_instrumentation_counter_;
460fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers
461725a957985171d712d5c048cc3d00ff14968784bjeffhao  DISALLOW_COPY_AND_ASSIGN(Instrumentation);
462725a957985171d712d5c048cc3d00ff14968784bjeffhao};
463725a957985171d712d5c048cc3d00ff14968784bjeffhao
46462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// An element in the instrumentation side stack maintained in art::Thread.
46562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstruct InstrumentationStackFrame {
466ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  InstrumentationStackFrame(mirror::Object* this_object, mirror::ArtMethod* method,
4679a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao                            uintptr_t return_pc, size_t frame_id, bool interpreter_entry)
4689a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao      : this_object_(this_object), method_(method), return_pc_(return_pc), frame_id_(frame_id),
4699a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao        interpreter_entry_(interpreter_entry) {
47062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
47162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
47262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
47362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
47462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  mirror::Object* this_object_;
475ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::ArtMethod* method_;
476138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  uintptr_t return_pc_;
477138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  size_t frame_id_;
478138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  bool interpreter_entry_;
47962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers};
48062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
48162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}  // namespace instrumentation
482725a957985171d712d5c048cc3d00ff14968784bjeffhao}  // namespace art
483725a957985171d712d5c048cc3d00ff14968784bjeffhao
484fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_INSTRUMENTATION_H_
485