instrumentation.h revision 3b05e9ba874449dbff65b01b8781001f7d93eea6
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
20ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "atomic.h"
21761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
22719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers#include "base/mutex.h"
233b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier#include "object_callbacks.h"
242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include <stdint.h>
26138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz#include <set>
2762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include <list>
28725a957985171d712d5c048cc3d00ff14968784bjeffhao
29725a957985171d712d5c048cc3d00ff14968784bjeffhaonamespace art {
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace mirror {
31ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class ArtMethod;
32ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Class;
33ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Object;
34ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  class Throwable;
3562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}  // namespace mirror
3662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersunion JValue;
37725a957985171d712d5c048cc3d00ff14968784bjeffhaoclass Thread;
3862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersclass ThrowLocation;
39725a957985171d712d5c048cc3d00ff14968784bjeffhao
4062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersnamespace instrumentation {
41725a957985171d712d5c048cc3d00ff14968784bjeffhao
42ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz// Interpreter handler tables.
43ee1997a3b83334985e757f369c09e111b121661bSebastien Hertzenum InterpreterHandlerTable {
44ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  kMainHandlerTable = 0,          // Main handler table: no suspend check, no instrumentation.
45ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  kAlternativeHandlerTable = 1,   // Alternative handler table: suspend check and/or instrumentation
46ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz                                  // enabled.
47ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  kNumHandlerTables
48ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz};
49ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
5062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// Instrumentation event listener API. Registered listeners will get the appropriate call back for
5162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// the events they are listening for. The call backs supply the thread, method and dex_pc the event
5262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// occurred upon. The thread may or may not be Thread::Current().
5362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstruct InstrumentationListener {
5462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  InstrumentationListener() {}
5562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual ~InstrumentationListener() {}
5662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
5762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is entered.
5862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
59ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                             mirror::ArtMethod* method,
6062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                             uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
6162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
6262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is exited.
6362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // TODO: its likely passing the return value would be useful, however, we may need to get and
6462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  //       parse the shorty to determine what kind of register holds the result.
6562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void MethodExited(Thread* thread, mirror::Object* this_object,
66ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                            mirror::ArtMethod* method, uint32_t dex_pc,
6762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                            const JValue& return_value)
6862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
6962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when a method is popped due to an exception throw. A method will either cause a
7162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // MethodExited call-back or a MethodUnwind call-back when its activation is removed.
7251db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz  virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
73ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                            mirror::ArtMethod* method, uint32_t dex_pc)
7451db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
7562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
7662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back for when the dex pc moves in a method.
7762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
78ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                          mirror::ArtMethod* method, uint32_t new_dex_pc)
7962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
8062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
8162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call-back when an exception is caught.
8262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  virtual void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
83ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                               mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
8462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                               mirror::Throwable* exception_object)
8562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
86725a957985171d712d5c048cc3d00ff14968784bjeffhao};
87725a957985171d712d5c048cc3d00ff14968784bjeffhao
8862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// Instrumentation is a catch-all for when extra information is required from the runtime. The
8962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// typical use for instrumentation is for profiling and debugging. Instrumentation may add stubs
9062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// to method entry and exit, it may also force execution to be switched to the interpreter and
9162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// trigger deoptimization.
92725a957985171d712d5c048cc3d00ff14968784bjeffhaoclass Instrumentation {
93725a957985171d712d5c048cc3d00ff14968784bjeffhao public:
9462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  enum InstrumentationEvent {
9562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kMethodEntered = 1,
9662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kMethodExited = 2,
9762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kMethodUnwind = 4,
9862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kDexPcMoved = 8,
9962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    kExceptionCaught = 16
10062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  };
10162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
1023b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  Instrumentation();
10362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
10462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Add a listener to be notified of the masked together sent of instrumentation events. This
10562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // suspend the runtime to install stubs. You are expected to hold the mutator lock as a proxy
10662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // for saying you should have suspended all threads (installing stubs while threads are running
10762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // will break).
10862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void AddListener(InstrumentationListener* listener, uint32_t events)
10962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
11062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
11162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
11262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Removes a listener possibly removing instrumentation stubs.
11362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void RemoveListener(InstrumentationListener* listener, uint32_t events)
11462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
11562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
11662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
117138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Deoptimization.
1183b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  void EnableDeoptimization() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
1193b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(deoptimized_methods_lock_);
1203b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  void DisableDeoptimization() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
1213b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier    LOCKS_EXCLUDED(deoptimized_methods_lock_);
12211d40c250ec86c784cf76b8c31e1cf9285d555dcSebastien Hertz  bool ShouldNotifyMethodEnterExitEvents() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
123138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
124138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Executes everything with interpreter.
125138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void DeoptimizeEverything()
126138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
127138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
128138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
129138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Executes everything with compiled code (or interpreter if there is no code).
130138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void UndeoptimizeEverything()
131138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
132138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
133138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
134138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Deoptimize a method by forcing its execution with the interpreter. Nevertheless, a static
135138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // method (except a class initializer) set to the resolution trampoline will be deoptimized only
136138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // once its declaring class is initialized.
137138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void Deoptimize(mirror::ArtMethod* method)
1383b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(Locks::thread_list_lock_, deoptimized_methods_lock_)
139138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
140138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
141138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Undeoptimze the method by restoring its entrypoints. Nevertheless, a static method
142138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // (except a class initializer) set to the resolution trampoline will be updated only once its
143138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // declaring class is initialized.
144138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void Undeoptimize(mirror::ArtMethod* method)
145138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_)
146138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
147138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
1483b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  bool IsDeoptimized(mirror::ArtMethod* method) const LOCKS_EXCLUDED(deoptimized_methods_lock_);
149138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
150138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Enable method tracing by installing instrumentation entry/exit stubs.
151138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void EnableMethodTracing()
152138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
153138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
154138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
155138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // Disable method tracing by uninstalling instrumentation entry/exit stubs.
156138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void DisableMethodTracing()
157138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
158138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_);
159138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
160ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  InterpreterHandlerTable GetInterpreterHandlerTable() const {
161ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz    return interpreter_handler_table_;
162ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  }
163ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
164d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier  void InstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_,
165d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier                                                        Locks::runtime_shutdown_lock_);
166d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier  void UninstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_,
167d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier                                                          Locks::runtime_shutdown_lock_);
168d889178ec78930538d9d6a66c3df9ee9afaffbb4Mathieu Chartier  void ResetQuickAllocEntryPoints() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
169fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers
17062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Update the code of a method respecting any installed stubs.
171ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code,
172ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                         const void* portable_code, bool have_portable_code) const
173138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
17462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Get the quick code for the given method. More efficient than asking the class linker as it
17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // will short-cut to GetCode if instrumentation and static method resolution stubs aren't
17762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // installed.
178ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetQuickCodeFor(mirror::ArtMethod* method) const
17962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
18062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
18162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ForceInterpretOnly() {
18262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    interpret_only_ = true;
18362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    forced_interpret_only_ = true;
18462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
18562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
186ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Called by ArtMethod::Invoke to determine dispatch mechanism.
18762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool InterpretOnly() const {
18862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return interpret_only_;
18962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
19062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
191563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi  bool IsForcedInterpretOnly() const {
192563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi    return forced_interpret_only_;
193563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi  }
194563b47cc142e477da244539b1d63070425e7fd78Hiroshi Yamauchi
19562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool ShouldPortableCodeDeoptimize() const {
19662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return instrumentation_stubs_installed_;
19762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
19862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
19962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool AreExitStubsInstalled() const {
20062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    return instrumentation_stubs_installed_;
20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
20262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
20374109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  bool HasMethodEntryListeners() const {
20474109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_method_entry_listeners_;
20574109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
20674109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
20774109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  bool HasMethodExitListeners() const {
20874109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_method_exit_listeners_;
20974109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
21074109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
21174109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  bool HasDexPcListeners() const {
21274109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    return have_dex_pc_listeners_;
21374109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz  }
21474109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz
215ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  bool IsActive() const {
216ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz    return have_dex_pc_listeners_ || have_method_entry_listeners_ || have_method_exit_listeners_ ||
217ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz        have_exception_caught_listeners_ || have_method_unwind_listeners_;
218ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  }
219ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
22062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been entered. A dex PC is provided as we may install
22162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // listeners into executing code and get method enter events for methods already on the stack.
22262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodEnterEvent(Thread* thread, mirror::Object* this_object,
223ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                        mirror::ArtMethod* method, uint32_t dex_pc) const
22462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
22574109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasMethodEntryListeners())) {
22662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      MethodEnterEventImpl(thread, this_object, method, dex_pc);
22762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
22862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
22962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
23062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been exited.
23162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodExitEvent(Thread* thread, mirror::Object* this_object,
232ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                       mirror::ArtMethod* method, uint32_t dex_pc,
23362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                       const JValue& return_value) const
23462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
23574109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasMethodExitListeners())) {
23662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      MethodExitEventImpl(thread, this_object, method, dex_pc, return_value);
23762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
23862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
23962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
24062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that a method has been exited due to an exception.
24162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
242ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                         mirror::ArtMethod* method, uint32_t dex_pc) const
24362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
24462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
24562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that the dex pc has moved (only supported by the interpreter).
24662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void DexPcMovedEvent(Thread* thread, mirror::Object* this_object,
247ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                       mirror::ArtMethod* method, uint32_t dex_pc) const
24862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
24974109f6683096de494b1457fa6d5b0ac33b4c98cSebastien Hertz    if (UNLIKELY(HasDexPcListeners())) {
25062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      DexPcMovedEventImpl(thread, this_object, method, dex_pc);
25162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    }
25262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
253725a957985171d712d5c048cc3d00ff14968784bjeffhao
25462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Inform listeners that an exception was caught.
25562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ExceptionCaughtEvent(Thread* thread, const ThrowLocation& throw_location,
256ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                            mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
257947ff080753c786a74f1cd7aeb09f717bb7074bdSebastien Hertz                            mirror::Throwable* exception_object) const
25862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
259725a957985171d712d5c048cc3d00ff14968784bjeffhao
26062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Called when an instrumented method is entered. The intended link register (lr) is saved so
26162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // that returning causes a branch to the method exit stub. Generates method enter events.
26262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void PushInstrumentationStackFrame(Thread* self, mirror::Object* this_object,
263ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                                     mirror::ArtMethod* method, uintptr_t lr,
2649a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao                                     bool interpreter_entry)
26562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
266725a957985171d712d5c048cc3d00ff14968784bjeffhao
26762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Called when an instrumented method is exited. Removes the pushed instrumentation frame
26862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // returning the intended link register. Generates method exit events.
26962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  uint64_t PopInstrumentationStackFrame(Thread* self, uintptr_t* return_pc, uint64_t gpr_result,
27062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                        uint64_t fpr_result)
27162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
272725a957985171d712d5c048cc3d00ff14968784bjeffhao
27362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Pops an instrumentation frame from the current thread and generate an unwind event.
27462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void PopMethodForUnwind(Thread* self, bool is_deoptimization) const
27562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
27662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
27762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Call back for configure stubs.
27862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool InstallStubsForClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
279725a957985171d712d5c048cc3d00ff14968784bjeffhao
280138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  void InstallStubsForMethod(mirror::ArtMethod* method)
281138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
282138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
2833b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  void VisitRoots(RootCallback* callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
2843b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(deoptimized_methods_lock_);
2853b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier
286725a957985171d712d5c048cc3d00ff14968784bjeffhao private:
28762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Does the job of installing or removing instrumentation code within methods.
28862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void ConfigureStubs(bool require_entry_exit_stubs, bool require_interpreter)
28962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
2903b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier      LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::classlinker_classes_lock_,
2913b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier                     deoptimized_methods_lock_);
29262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
293ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  void UpdateInterpreterHandlerTable() {
294ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz    interpreter_handler_table_ = IsActive() ? kAlternativeHandlerTable : kMainHandlerTable;
295ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  }
296ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
297661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  // No thread safety analysis to get around SetQuickAllocEntryPointsInstrumented requiring
298661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  // exclusive access to mutator lock which you can't get if the runtime isn't started.
299661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  void SetEntrypointsInstrumented(bool instrumented) NO_THREAD_SAFETY_ANALYSIS;
300661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier
30162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
302ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                            mirror::ArtMethod* method, uint32_t dex_pc) const
30362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
30462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
305ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                           mirror::ArtMethod* method,
30662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                           uint32_t dex_pc, const JValue& return_value) const
30762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
30862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  void DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
309ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                           mirror::ArtMethod* method, uint32_t dex_pc) const
31062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
31162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
312ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ so that it calls instrumentation/interpreter code?
31362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool instrumentation_stubs_installed_;
31462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
315ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ to reference the enter/exit stubs?
31662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool entry_exit_stubs_installed_;
31762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
318ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  // Have we hijacked ArtMethod::code_ to reference the enter interpreter stub?
31962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool interpreter_stubs_installed_;
32062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
32162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we need the fidelity of events that we only get from running within the interpreter?
32262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool interpret_only_;
323725a957985171d712d5c048cc3d00ff14968784bjeffhao
32462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Did the runtime request we only run in the interpreter? ie -Xint mode.
32562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool forced_interpret_only_;
326725a957985171d712d5c048cc3d00ff14968784bjeffhao
32762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method entry events? Short-cut to avoid taking the
32862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
32962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_method_entry_listeners_;
33062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
33162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method exit events? Short-cut to avoid taking the
33262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
33362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_method_exit_listeners_;
33462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
33562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for method unwind events? Short-cut to avoid taking the
33662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
33762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_method_unwind_listeners_;
33862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
33962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any listeners for dex move events? Short-cut to avoid taking the
34062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // instrumentation_lock_.
34162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_dex_pc_listeners_;
34262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
34362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // Do we have any exception caught listeners? Short-cut to avoid taking the instrumentation_lock_.
34462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  bool have_exception_caught_listeners_;
34562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
34662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  // The event listeners, written to with the mutator_lock_ exclusively held.
34762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_entry_listeners_ GUARDED_BY(Locks::mutator_lock_);
34862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_exit_listeners_ GUARDED_BY(Locks::mutator_lock_);
34962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> method_unwind_listeners_ GUARDED_BY(Locks::mutator_lock_);
35062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
35162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::list<InstrumentationListener*> exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
352725a957985171d712d5c048cc3d00ff14968784bjeffhao
353138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // The set of methods being deoptimized (by the debugger) which must be executed with interpreter
354138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  // only.
3553b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  mutable ReaderWriterMutex deoptimized_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
3563b05e9ba874449dbff65b01b8781001f7d93eea6Mathieu Chartier  std::set<mirror::ArtMethod*> deoptimized_methods_ GUARDED_BY(deoptimized_methods_lock_);
35711d40c250ec86c784cf76b8c31e1cf9285d555dcSebastien Hertz  bool deoptimization_enabled_;
358138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz
359fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // Current interpreter handler table. This is updated each time the thread state flags are
360fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // modified.
361ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz  InterpreterHandlerTable interpreter_handler_table_;
362ee1997a3b83334985e757f369c09e111b121661bSebastien Hertz
363fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // Greater than 0 if quick alloc entry points instrumented.
364fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers  // TODO: The access and changes to this is racy and should be guarded by a lock.
365cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier  AtomicInteger quick_alloc_entry_points_instrumentation_counter_;
366fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers
367725a957985171d712d5c048cc3d00ff14968784bjeffhao  DISALLOW_COPY_AND_ASSIGN(Instrumentation);
368725a957985171d712d5c048cc3d00ff14968784bjeffhao};
369725a957985171d712d5c048cc3d00ff14968784bjeffhao
37062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers// An element in the instrumentation side stack maintained in art::Thread.
37162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstruct InstrumentationStackFrame {
372ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  InstrumentationStackFrame(mirror::Object* this_object, mirror::ArtMethod* method,
3739a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao                            uintptr_t return_pc, size_t frame_id, bool interpreter_entry)
3749a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao      : this_object_(this_object), method_(method), return_pc_(return_pc), frame_id_(frame_id),
3759a916d3c0d0574d106c764e737c67b52988d6139Jeff Hao        interpreter_entry_(interpreter_entry) {
37662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  }
37762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
37862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
37962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
38062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  mirror::Object* this_object_;
381ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  mirror::ArtMethod* method_;
382138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  uintptr_t return_pc_;
383138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  size_t frame_id_;
384138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz  bool interpreter_entry_;
38562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers};
38662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers
38762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}  // namespace instrumentation
388725a957985171d712d5c048cc3d00ff14968784bjeffhao}  // namespace art
389725a957985171d712d5c048cc3d00ff14968784bjeffhao
390fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_INSTRUMENTATION_H_
391