instrumentation.h revision ea46f950e7a51585db293cd7f047de190a482414
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
20761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
2162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "locks.h"
222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include <stdint.h>
2462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include <list>
25725a957985171d712d5c048cc3d00ff14968784bjeffhao
26725a957985171d712d5c048cc3d00ff14968784bjeffhaonamespace art {
272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace mirror {
28ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class ArtMethod;
29ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Class;
30ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Object;
31ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Throwable;
3262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}  // namespace mirror
3362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersunion JValue;
34725a957985171d712d5c048cc3d00ff14968784bjeffhaoclass Thread;
3562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersclass ThrowLocation;
36725a957985171d712d5c048cc3d00ff14968784bjeffhao
3762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersnamespace instrumentation {
38725a957985171d712d5c048cc3d00ff14968784bjeffhao
3962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersconst bool kVerboseInstrumentation = false;
4062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
4162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// Instrumentation event listener API. Registered listeners will get the appropriate call back for
4262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// the events they are listening for. The call backs supply the thread, method and dex_pc the event
4362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// occurred upon. The thread may or may not be Thread::Current().
4462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstruct InstrumentationListener {
4562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  InstrumentationListener() {}
4662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual ~InstrumentationListener() {}
4762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
4862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is entered.
4962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
50ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                             const mirror::ArtMethod* method,
5162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                             uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
5262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
5362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is exited.
5462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // TODO: its likely passing the return value would be useful, however, we may need to get and
5562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  //       parse the shorty to determine what kind of register holds the result.
5662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void MethodExited(Thread* thread, mirror::Object* this_object,
57ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                            const mirror::ArtMethod* method, uint32_t dex_pc,
5862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            const JValue& return_value)
5962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
6062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
6162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is popped due to an exception throw. A method will either cause a
6262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // MethodExited call-back or a MethodUnwind call-back when its activation is removed.
63ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  virtual void MethodUnwind(Thread* thread, const mirror::ArtMethod* method,
6462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
6562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
6662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when the dex pc moves in a method.
6762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
68ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                          const mirror::ArtMethod* method, uint32_t new_dex_pc)
6962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
7062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back when an exception is caught.
7262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
73ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                               mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
7462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                               mirror::Throwable* exception_object)
7562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
76725a957985171d712d5c048cc3d00ff14968784bjeffhao};
77725a957985171d712d5c048cc3d00ff14968784bjeffhao
7862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// Instrumentation is a catch-all for when extra information is required from the runtime. The
7962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// typical use for instrumentation is for profiling and debugging. Instrumentation may add stubs
8062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// to method entry and exit, it may also force execution to be switched to the interpreter and
8162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// trigger deoptimization.
82725a957985171d712d5c048cc3d00ff14968784bjeffhaoclass Instrumentation {
83725a957985171d712d5c048cc3d00ff14968784bjeffhao public:
8462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  enum InstrumentationEvent {
8562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kMethodEntered = 1,
8662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kMethodExited = 2,
8762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kMethodUnwind = 4,
8862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kDexPcMoved = 8,
8962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kExceptionCaught = 16
9062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  };
9162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
9262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Instrumentation() :
9362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      instrumentation_stubs_installed_(false), entry_exit_stubs_installed_(false),
9462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      interpreter_stubs_installed_(false),
9562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      interpret_only_(false), forced_interpret_only_(false),
9662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      have_method_entry_listeners_(false), have_method_exit_listeners_(false),
9762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      have_method_unwind_listeners_(false), have_dex_pc_listeners_(false),
9862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      have_exception_caught_listeners_(false) {}
9962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
10062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Add a listener to be notified of the masked together sent of instrumentation events. This
10162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // suspend the runtime to install stubs. You are expected to hold the mutator lock as a proxy
10262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // for saying you should have suspended all threads (installing stubs while threads are running
10362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // will break).
10462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void AddListener(InstrumentationListener* listener, uint32_t events)
10562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
10662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
10762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
10862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Removes a listener possibly removing instrumentation stubs.
10962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void RemoveListener(InstrumentationListener* listener, uint32_t events)
11062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
11162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
11262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
11362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Update the code of a method respecting any installed stubs.
114ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  void UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const;
11562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Get the quick code for the given method. More efficient than asking the class linker as it
11762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // will short-cut to GetCode if instrumentation and static method resolution stubs aren't
11862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // installed.
119ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  const void* GetQuickCodeFor(const mirror::ArtMethod* method) const
12062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
12162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
12262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ForceInterpretOnly() {
12362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    interpret_only_ = true;
12462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    forced_interpret_only_ = true;
12562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
12662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
127ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Called by ArtMethod::Invoke to determine dispatch mechanism.
12862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool InterpretOnly() const {
12962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return interpret_only_;
13062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
13162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
13262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool ShouldPortableCodeDeoptimize() const {
13362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return instrumentation_stubs_installed_;
13462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
13562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
13662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool AreExitStubsInstalled() const {
13762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return instrumentation_stubs_installed_;
13862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
13962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
14074109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  bool HasMethodEntryListeners() const {
14174109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_method_entry_listeners_;
14274109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
14374109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
14474109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  bool HasMethodExitListeners() const {
14574109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_method_exit_listeners_;
14674109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
14774109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
14874109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  bool HasDexPcListeners() const {
14974109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_dex_pc_listeners_;
15074109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
15174109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
15262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been entered. A dex PC is provided as we may install
15362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // listeners into executing code and get method enter events for methods already on the stack.
15462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodEnterEvent(Thread* thread, mirror::Object* this_object,
155ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                        const mirror::ArtMethod* method, uint32_t dex_pc) const
15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
15774109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasMethodEntryListeners())) {
15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      MethodEnterEventImpl(thread, this_object, method, dex_pc);
15962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
16062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
16162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
16262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been exited.
16362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodExitEvent(Thread* thread, mirror::Object* this_object,
164ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                       const mirror::ArtMethod* method, uint32_t dex_pc,
16562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                       const JValue& return_value) const
16662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
16774109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasMethodExitListeners())) {
16862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      MethodExitEventImpl(thread, this_object, method, dex_pc, return_value);
16962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
17062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
17162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
17262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been exited due to an exception.
17362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
174ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                         const mirror::ArtMethod* method, uint32_t dex_pc) const
17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
17762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that the dex pc has moved (only supported by the interpreter).
17862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void DexPcMovedEvent(Thread* thread, mirror::Object* this_object,
179ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                       const mirror::ArtMethod* method, uint32_t dex_pc) const
18062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
18174109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasDexPcListeners())) {
18262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      DexPcMovedEventImpl(thread, this_object, method, dex_pc);
18362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
18462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
185725a957985171d712d5c048cc3d00ff14968784bjeffhao
18662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that an exception was caught.
18762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ExceptionCaughtEvent(Thread* thread, const ThrowLocation& throw_location,
188ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                            mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
18962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            mirror::Throwable* exception_object)
19062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
191725a957985171d712d5c048cc3d00ff14968784bjeffhao
19262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Called when an instrumented method is entered. The intended link register (lr) is saved so
19362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // that returning causes a branch to the method exit stub. Generates method enter events.
19462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void PushInstrumentationStackFrame(Thread* self, mirror::Object* this_object,
195ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                     mirror::ArtMethod* method, uintptr_t lr,
1969a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao                                     bool interpreter_entry)
19762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
198725a957985171d712d5c048cc3d00ff14968784bjeffhao
19962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Called when an instrumented method is exited. Removes the pushed instrumentation frame
20062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // returning the intended link register. Generates method exit events.
20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint64_t PopInstrumentationStackFrame(Thread* self, uintptr_t* return_pc, uint64_t gpr_result,
20262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                        uint64_t fpr_result)
20362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
204725a957985171d712d5c048cc3d00ff14968784bjeffhao
20562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Pops an instrumentation frame from the current thread and generate an unwind event.
20662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void PopMethodForUnwind(Thread* self, bool is_deoptimization) const
20762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
20862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
20962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call back for configure stubs.
21062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool InstallStubsForClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
211725a957985171d712d5c048cc3d00ff14968784bjeffhao
212725a957985171d712d5c048cc3d00ff14968784bjeffhao private:
21362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Does the job of installing or removing instrumentation code within methods.
21462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ConfigureStubs(bool require_entry_exit_stubs, bool require_interpreter)
21562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
21662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
21762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
21862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
219ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                            const mirror::ArtMethod* method, uint32_t dex_pc) const
22062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
22162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
222ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                           const mirror::ArtMethod* method,
22362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                           uint32_t dex_pc, const JValue& return_value) const
22462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
22562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
226ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                           const mirror::ArtMethod* method, uint32_t dex_pc) const
22762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
22862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
229ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ so that it calls instrumentation/interpreter code?
23062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool instrumentation_stubs_installed_;
23162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
232ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ to reference the enter/exit stubs?
23362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool entry_exit_stubs_installed_;
23462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
235ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ to reference the enter interpreter stub?
23662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool interpreter_stubs_installed_;
23762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
23862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we need the fidelity of events that we only get from running within the interpreter?
23962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool interpret_only_;
240725a957985171d712d5c048cc3d00ff14968784bjeffhao
24162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Did the runtime request we only run in the interpreter? ie -Xint mode.
24262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool forced_interpret_only_;
243725a957985171d712d5c048cc3d00ff14968784bjeffhao
24462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method entry events? Short-cut to avoid taking the
24562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
24662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_method_entry_listeners_;
24762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
24862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method exit events? Short-cut to avoid taking the
24962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
25062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_method_exit_listeners_;
25162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
25262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method unwind events? Short-cut to avoid taking the
25362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
25462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_method_unwind_listeners_;
25562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
25662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for dex move events? Short-cut to avoid taking the
25762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
25862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_dex_pc_listeners_;
25962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
26062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any exception caught listeners? Short-cut to avoid taking the instrumentation_lock_.
26162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_exception_caught_listeners_;
26262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
26362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // The event listeners, written to with the mutator_lock_ exclusively held.
26462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_entry_listeners_ GUARDED_BY(Locks::mutator_lock_);
26562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_exit_listeners_ GUARDED_BY(Locks::mutator_lock_);
26662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_unwind_listeners_ GUARDED_BY(Locks::mutator_lock_);
26762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
26862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
269725a957985171d712d5c048cc3d00ff14968784bjeffhao
270725a957985171d712d5c048cc3d00ff14968784bjeffhao  DISALLOW_COPY_AND_ASSIGN(Instrumentation);
271725a957985171d712d5c048cc3d00ff14968784bjeffhao};
272725a957985171d712d5c048cc3d00ff14968784bjeffhao
27362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// An element in the instrumentation side stack maintained in art::Thread.
27462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstruct InstrumentationStackFrame {
275ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  InstrumentationStackFrame(mirror::Object* this_object, mirror::ArtMethod* method,
2769a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao                            uintptr_t return_pc, size_t frame_id, bool interpreter_entry)
2779a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao      : this_object_(this_object), method_(method), return_pc_(return_pc), frame_id_(frame_id),
2789a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao        interpreter_entry_(interpreter_entry) {
27962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
28062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
28162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
28262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
28362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  mirror::Object* this_object_;
284ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::ArtMethod* method_;
28562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  const uintptr_t return_pc_;
28662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  const size_t frame_id_;
28765d15d985a27be01e1d64f473af0e9d8eb19051dJeff Hao  const bool interpreter_entry_;
28862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers};
28962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
29062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}  // namespace instrumentation
291725a957985171d712d5c048cc3d00ff14968784bjeffhao}  // namespace art
292725a957985171d712d5c048cc3d00ff14968784bjeffhao
293fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_INSTRUMENTATION_H_
294