summaryrefslogtreecommitdiff
path: root/runtime/instrumentation.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/instrumentation.h')
-rw-r--r--runtime/instrumentation.h26
1 files changed, 18 insertions, 8 deletions
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 612ca14cf5..726cf1b461 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -397,6 +397,11 @@ class Instrumentation {
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!Locks::thread_list_lock_);
+ static size_t ComputeFrameId(Thread* self,
+ size_t frame_depth,
+ size_t inlined_frames_before_frame)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
private:
InstrumentationLevel GetCurrentInstrumentationLevel() const;
@@ -512,20 +517,25 @@ class Instrumentation {
InstrumentationLevelTable requested_instrumentation_levels_ GUARDED_BY(Locks::mutator_lock_);
// The event listeners, written to with the mutator_lock_ exclusively held.
+ // Mutators must be able to iterate over these lists concurrently, that is, with listeners being
+ // added or removed while iterating. The modifying thread holds exclusive lock,
+ // so other threads cannot iterate (i.e. read the data of the list) at the same time but they
+ // do keep iterators that need to remain valid. This is the reason these listeners are std::list
+ // and not for example std::vector: the existing storage for a std::list does not move.
+ // Note that mutators cannot make a copy of these lists before iterating, as the instrumentation
+ // listeners can also be deleted concurrently.
+ // As a result, these lists are never trimmed. That's acceptable given the low number of
+ // listeners we have.
std::list<InstrumentationListener*> method_entry_listeners_ GUARDED_BY(Locks::mutator_lock_);
std::list<InstrumentationListener*> method_exit_listeners_ GUARDED_BY(Locks::mutator_lock_);
std::list<InstrumentationListener*> method_unwind_listeners_ GUARDED_BY(Locks::mutator_lock_);
std::list<InstrumentationListener*> backward_branch_listeners_ GUARDED_BY(Locks::mutator_lock_);
std::list<InstrumentationListener*> invoke_virtual_or_interface_listeners_
GUARDED_BY(Locks::mutator_lock_);
- std::shared_ptr<std::list<InstrumentationListener*>> dex_pc_listeners_
- GUARDED_BY(Locks::mutator_lock_);
- std::shared_ptr<std::list<InstrumentationListener*>> field_read_listeners_
- GUARDED_BY(Locks::mutator_lock_);
- std::shared_ptr<std::list<InstrumentationListener*>> field_write_listeners_
- GUARDED_BY(Locks::mutator_lock_);
- std::shared_ptr<std::list<InstrumentationListener*>> exception_caught_listeners_
- GUARDED_BY(Locks::mutator_lock_);
+ std::list<InstrumentationListener*> dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
+ std::list<InstrumentationListener*> field_read_listeners_ GUARDED_BY(Locks::mutator_lock_);
+ std::list<InstrumentationListener*> field_write_listeners_ GUARDED_BY(Locks::mutator_lock_);
+ std::list<InstrumentationListener*> exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
// The set of methods being deoptimized (by the debugger) which must be executed with interpreter
// only.