xref: /aosp_15_r20/art/openjdkjvmti/events-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_OPENJDKJVMTI_EVENTS_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_OPENJDKJVMTI_EVENTS_INL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <array>
21*795d594fSAndroid Build Coastguard Worker #include <type_traits>
22*795d594fSAndroid Build Coastguard Worker #include <tuple>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "base/mutex-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "events.h"
26*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
27*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
28*795d594fSAndroid Build Coastguard Worker #include "runtime-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "stack.h"
31*795d594fSAndroid Build Coastguard Worker #include "ti_breakpoint.h"
32*795d594fSAndroid Build Coastguard Worker #include "ti_thread.h"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
37*795d594fSAndroid Build Coastguard Worker 
GetArtJvmtiEvent(ArtJvmTiEnv * env,jvmtiEvent e)38*795d594fSAndroid Build Coastguard Worker static inline ArtJvmtiEvent GetArtJvmtiEvent(ArtJvmTiEnv* env, jvmtiEvent e) {
39*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(e == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
40*795d594fSAndroid Build Coastguard Worker     if (env->capabilities.can_retransform_classes) {
41*795d594fSAndroid Build Coastguard Worker       return ArtJvmtiEvent::kClassFileLoadHookRetransformable;
42*795d594fSAndroid Build Coastguard Worker     } else {
43*795d594fSAndroid Build Coastguard Worker       return ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
44*795d594fSAndroid Build Coastguard Worker     }
45*795d594fSAndroid Build Coastguard Worker   } else {
46*795d594fSAndroid Build Coastguard Worker     return static_cast<ArtJvmtiEvent>(e);
47*795d594fSAndroid Build Coastguard Worker   }
48*795d594fSAndroid Build Coastguard Worker }
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker namespace impl {
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker // Helper for ensuring that the dispatch environment is suitably provisioned. Events with JNIEnvs
53*795d594fSAndroid Build Coastguard Worker // need to stash pending exceptions since they can cause new ones to be thrown. In accordance with
54*795d594fSAndroid Build Coastguard Worker // the JVMTI specification we allow exceptions originating from events to overwrite the current
55*795d594fSAndroid Build Coastguard Worker // exception, including exceptions originating from earlier events.
56*795d594fSAndroid Build Coastguard Worker class ScopedEventDispatchEnvironment final : public art::ValueObject {
57*795d594fSAndroid Build Coastguard Worker  public:
ScopedEventDispatchEnvironment()58*795d594fSAndroid Build Coastguard Worker   ScopedEventDispatchEnvironment() : env_(nullptr), throw_(nullptr, nullptr) {
59*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(art::Thread::Current()->GetState(), art::ThreadState::kNative);
60*795d594fSAndroid Build Coastguard Worker   }
61*795d594fSAndroid Build Coastguard Worker 
ScopedEventDispatchEnvironment(JNIEnv * env)62*795d594fSAndroid Build Coastguard Worker   explicit ScopedEventDispatchEnvironment(JNIEnv* env)
63*795d594fSAndroid Build Coastguard Worker       : env_(env),
64*795d594fSAndroid Build Coastguard Worker         throw_(env_, env_->ExceptionOccurred()) {
65*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(art::Thread::Current()->GetState(), art::ThreadState::kNative);
66*795d594fSAndroid Build Coastguard Worker     // The spec doesn't say how much local data should be there, so we just give 128 which seems
67*795d594fSAndroid Build Coastguard Worker     // likely to be enough for most cases.
68*795d594fSAndroid Build Coastguard Worker     env_->PushLocalFrame(128);
69*795d594fSAndroid Build Coastguard Worker     env_->ExceptionClear();
70*795d594fSAndroid Build Coastguard Worker   }
71*795d594fSAndroid Build Coastguard Worker 
~ScopedEventDispatchEnvironment()72*795d594fSAndroid Build Coastguard Worker   ~ScopedEventDispatchEnvironment() {
73*795d594fSAndroid Build Coastguard Worker     if (env_ != nullptr) {
74*795d594fSAndroid Build Coastguard Worker       if (throw_.get() != nullptr && !env_->ExceptionCheck()) {
75*795d594fSAndroid Build Coastguard Worker         // TODO It would be nice to add the overwritten exceptions to the suppressed exceptions list
76*795d594fSAndroid Build Coastguard Worker         // of the newest exception.
77*795d594fSAndroid Build Coastguard Worker         env_->Throw(throw_.get());
78*795d594fSAndroid Build Coastguard Worker       }
79*795d594fSAndroid Build Coastguard Worker       env_->PopLocalFrame(nullptr);
80*795d594fSAndroid Build Coastguard Worker     }
81*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(art::Thread::Current()->GetState(), art::ThreadState::kNative);
82*795d594fSAndroid Build Coastguard Worker   }
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker  private:
85*795d594fSAndroid Build Coastguard Worker   JNIEnv* env_;
86*795d594fSAndroid Build Coastguard Worker   ScopedLocalRef<jthrowable> throw_;
87*795d594fSAndroid Build Coastguard Worker 
88*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedEventDispatchEnvironment);
89*795d594fSAndroid Build Coastguard Worker };
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker // Infrastructure to achieve type safety for event dispatch.
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker #define FORALL_EVENT_TYPES(fn)                                                         \
94*795d594fSAndroid Build Coastguard Worker   fn(VMInit,                    ArtJvmtiEvent::kVmInit)                                \
95*795d594fSAndroid Build Coastguard Worker   fn(VMDeath,                   ArtJvmtiEvent::kVmDeath)                               \
96*795d594fSAndroid Build Coastguard Worker   fn(ThreadStart,               ArtJvmtiEvent::kThreadStart)                           \
97*795d594fSAndroid Build Coastguard Worker   fn(ThreadEnd,                 ArtJvmtiEvent::kThreadEnd)                             \
98*795d594fSAndroid Build Coastguard Worker   fn(ClassFileLoadHook,         ArtJvmtiEvent::kClassFileLoadHookRetransformable)      \
99*795d594fSAndroid Build Coastguard Worker   fn(ClassFileLoadHook,         ArtJvmtiEvent::kClassFileLoadHookNonRetransformable)   \
100*795d594fSAndroid Build Coastguard Worker   fn(ClassLoad,                 ArtJvmtiEvent::kClassLoad)                             \
101*795d594fSAndroid Build Coastguard Worker   fn(ClassPrepare,              ArtJvmtiEvent::kClassPrepare)                          \
102*795d594fSAndroid Build Coastguard Worker   fn(VMStart,                   ArtJvmtiEvent::kVmStart)                               \
103*795d594fSAndroid Build Coastguard Worker   fn(Exception,                 ArtJvmtiEvent::kException)                             \
104*795d594fSAndroid Build Coastguard Worker   fn(ExceptionCatch,            ArtJvmtiEvent::kExceptionCatch)                        \
105*795d594fSAndroid Build Coastguard Worker   fn(SingleStep,                ArtJvmtiEvent::kSingleStep)                            \
106*795d594fSAndroid Build Coastguard Worker   fn(FramePop,                  ArtJvmtiEvent::kFramePop)                              \
107*795d594fSAndroid Build Coastguard Worker   fn(Breakpoint,                ArtJvmtiEvent::kBreakpoint)                            \
108*795d594fSAndroid Build Coastguard Worker   fn(FieldAccess,               ArtJvmtiEvent::kFieldAccess)                           \
109*795d594fSAndroid Build Coastguard Worker   fn(FieldModification,         ArtJvmtiEvent::kFieldModification)                     \
110*795d594fSAndroid Build Coastguard Worker   fn(MethodEntry,               ArtJvmtiEvent::kMethodEntry)                           \
111*795d594fSAndroid Build Coastguard Worker   fn(MethodExit,                ArtJvmtiEvent::kMethodExit)                            \
112*795d594fSAndroid Build Coastguard Worker   fn(NativeMethodBind,          ArtJvmtiEvent::kNativeMethodBind)                      \
113*795d594fSAndroid Build Coastguard Worker   fn(CompiledMethodLoad,        ArtJvmtiEvent::kCompiledMethodLoad)                    \
114*795d594fSAndroid Build Coastguard Worker   fn(CompiledMethodUnload,      ArtJvmtiEvent::kCompiledMethodUnload)                  \
115*795d594fSAndroid Build Coastguard Worker   fn(DynamicCodeGenerated,      ArtJvmtiEvent::kDynamicCodeGenerated)                  \
116*795d594fSAndroid Build Coastguard Worker   fn(DataDumpRequest,           ArtJvmtiEvent::kDataDumpRequest)                       \
117*795d594fSAndroid Build Coastguard Worker   fn(MonitorWait,               ArtJvmtiEvent::kMonitorWait)                           \
118*795d594fSAndroid Build Coastguard Worker   fn(MonitorWaited,             ArtJvmtiEvent::kMonitorWaited)                         \
119*795d594fSAndroid Build Coastguard Worker   fn(MonitorContendedEnter,     ArtJvmtiEvent::kMonitorContendedEnter)                 \
120*795d594fSAndroid Build Coastguard Worker   fn(MonitorContendedEntered,   ArtJvmtiEvent::kMonitorContendedEntered)               \
121*795d594fSAndroid Build Coastguard Worker   fn(ResourceExhausted,         ArtJvmtiEvent::kResourceExhausted)                     \
122*795d594fSAndroid Build Coastguard Worker   fn(GarbageCollectionStart,    ArtJvmtiEvent::kGarbageCollectionStart)                \
123*795d594fSAndroid Build Coastguard Worker   fn(GarbageCollectionFinish,   ArtJvmtiEvent::kGarbageCollectionFinish)               \
124*795d594fSAndroid Build Coastguard Worker   fn(ObjectFree,                ArtJvmtiEvent::kObjectFree)                            \
125*795d594fSAndroid Build Coastguard Worker   fn(VMObjectAlloc,             ArtJvmtiEvent::kVmObjectAlloc)                         \
126*795d594fSAndroid Build Coastguard Worker   fn(DdmPublishChunk,           ArtJvmtiEvent::kDdmPublishChunk)                       \
127*795d594fSAndroid Build Coastguard Worker   fn(ObsoleteObjectCreated,     ArtJvmtiEvent::kObsoleteObjectCreated)                 \
128*795d594fSAndroid Build Coastguard Worker   fn(StructuralDexFileLoadHook, ArtJvmtiEvent::kStructuralDexFileLoadHook)
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent>
131*795d594fSAndroid Build Coastguard Worker struct EventFnType {
132*795d594fSAndroid Build Coastguard Worker };
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker #define EVENT_FN_TYPE(name, enum_name)                    \
135*795d594fSAndroid Build Coastguard Worker template <>                                               \
136*795d594fSAndroid Build Coastguard Worker struct EventFnType<enum_name> {                           \
137*795d594fSAndroid Build Coastguard Worker   using type = decltype(ArtJvmtiEventCallbacks().name);   \
138*795d594fSAndroid Build Coastguard Worker };
139*795d594fSAndroid Build Coastguard Worker 
140*795d594fSAndroid Build Coastguard Worker FORALL_EVENT_TYPES(EVENT_FN_TYPE)
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker #undef EVENT_FN_TYPE
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker #define MAKE_EVENT_HANDLER_FUNC(name, enum_name)                                          \
145*795d594fSAndroid Build Coastguard Worker template<>                                                                                \
146*795d594fSAndroid Build Coastguard Worker struct EventHandlerFunc<enum_name> {                                                      \
147*795d594fSAndroid Build Coastguard Worker   using EventFnType = typename impl::EventFnType<enum_name>::type;                        \
148*795d594fSAndroid Build Coastguard Worker   explicit EventHandlerFunc(ArtJvmTiEnv* env)                                             \
149*795d594fSAndroid Build Coastguard Worker       : env_(env),                                                                        \
150*795d594fSAndroid Build Coastguard Worker         fn_(env_->event_callbacks == nullptr ? nullptr : env_->event_callbacks->name) { } \
151*795d594fSAndroid Build Coastguard Worker                                                                                           \
152*795d594fSAndroid Build Coastguard Worker   template <typename ...Args>                                                             \
153*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE                                                                           \
154*795d594fSAndroid Build Coastguard Worker   void ExecuteCallback(JNIEnv* jnienv, Args... args) const {                              \
155*795d594fSAndroid Build Coastguard Worker     if (fn_ != nullptr) {                                                                 \
156*795d594fSAndroid Build Coastguard Worker       ScopedEventDispatchEnvironment sede(jnienv);                                        \
157*795d594fSAndroid Build Coastguard Worker       DoExecute(jnienv, args...);                                                         \
158*795d594fSAndroid Build Coastguard Worker     }                                                                                     \
159*795d594fSAndroid Build Coastguard Worker   }                                                                                       \
160*795d594fSAndroid Build Coastguard Worker                                                                                           \
161*795d594fSAndroid Build Coastguard Worker   template <typename ...Args>                                                             \
162*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE                                                                           \
163*795d594fSAndroid Build Coastguard Worker   void ExecuteCallback(Args... args) const {                                              \
164*795d594fSAndroid Build Coastguard Worker     if (fn_ != nullptr) {                                                                 \
165*795d594fSAndroid Build Coastguard Worker       ScopedEventDispatchEnvironment sede;                                                \
166*795d594fSAndroid Build Coastguard Worker       DoExecute(args...);                                                                 \
167*795d594fSAndroid Build Coastguard Worker     }                                                                                     \
168*795d594fSAndroid Build Coastguard Worker   }                                                                                       \
169*795d594fSAndroid Build Coastguard Worker                                                                                           \
170*795d594fSAndroid Build Coastguard Worker  private:                                                                                 \
171*795d594fSAndroid Build Coastguard Worker   template <typename ...Args>                                                             \
172*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE                                                                           \
173*795d594fSAndroid Build Coastguard Worker   inline void DoExecute(Args... args) const {                                             \
174*795d594fSAndroid Build Coastguard Worker     static_assert(std::is_same<EventFnType, void(*)(jvmtiEnv*, Args...)>::value,          \
175*795d594fSAndroid Build Coastguard Worker           "Unexpected different type of ExecuteCallback");                                \
176*795d594fSAndroid Build Coastguard Worker     fn_(env_, args...);                                                                   \
177*795d594fSAndroid Build Coastguard Worker   }                                                                                       \
178*795d594fSAndroid Build Coastguard Worker                                                                                           \
179*795d594fSAndroid Build Coastguard Worker  public:                                                                                  \
180*795d594fSAndroid Build Coastguard Worker   ArtJvmTiEnv* env_;                                                                      \
181*795d594fSAndroid Build Coastguard Worker   EventFnType fn_;                                                                        \
182*795d594fSAndroid Build Coastguard Worker };
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker FORALL_EVENT_TYPES(MAKE_EVENT_HANDLER_FUNC)
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker #undef MAKE_EVENT_HANDLER_FUNC
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker #undef FORALL_EVENT_TYPES
189*795d594fSAndroid Build Coastguard Worker 
190*795d594fSAndroid Build Coastguard Worker }  // namespace impl
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename ...Args>
CollectEvents(art::Thread * thread,Args...args)193*795d594fSAndroid Build Coastguard Worker inline std::vector<impl::EventHandlerFunc<kEvent>> EventHandler::CollectEvents(art::Thread* thread,
194*795d594fSAndroid Build Coastguard Worker                                                                                Args... args) const {
195*795d594fSAndroid Build Coastguard Worker   art::ReaderMutexLock mu(thread, envs_lock_);
196*795d594fSAndroid Build Coastguard Worker   std::vector<impl::EventHandlerFunc<kEvent>> handlers;
197*795d594fSAndroid Build Coastguard Worker   for (ArtJvmTiEnv* env : envs) {
198*795d594fSAndroid Build Coastguard Worker     if (ShouldDispatch<kEvent>(env, thread, args...)) {
199*795d594fSAndroid Build Coastguard Worker       impl::EventHandlerFunc<kEvent> h(env);
200*795d594fSAndroid Build Coastguard Worker       handlers.push_back(h);
201*795d594fSAndroid Build Coastguard Worker     }
202*795d594fSAndroid Build Coastguard Worker   }
203*795d594fSAndroid Build Coastguard Worker   return handlers;
204*795d594fSAndroid Build Coastguard Worker }
205*795d594fSAndroid Build Coastguard Worker 
206*795d594fSAndroid Build Coastguard Worker // C++ does not allow partial template function specialization. The dispatch for our separated
207*795d594fSAndroid Build Coastguard Worker // ClassFileLoadHook event types is the same, so use this helper for code deduplication.
208*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent>
DispatchClassFileLoadHookEvent(art::Thread * thread,JNIEnv * jnienv,jclass class_being_redefined,jobject loader,const char * name,jobject protection_domain,jint class_data_len,const unsigned char * class_data,jint * new_class_data_len,unsigned char ** new_class_data)209*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchClassFileLoadHookEvent(art::Thread* thread,
210*795d594fSAndroid Build Coastguard Worker                                                          JNIEnv* jnienv,
211*795d594fSAndroid Build Coastguard Worker                                                          jclass class_being_redefined,
212*795d594fSAndroid Build Coastguard Worker                                                          jobject loader,
213*795d594fSAndroid Build Coastguard Worker                                                          const char* name,
214*795d594fSAndroid Build Coastguard Worker                                                          jobject protection_domain,
215*795d594fSAndroid Build Coastguard Worker                                                          jint class_data_len,
216*795d594fSAndroid Build Coastguard Worker                                                          const unsigned char* class_data,
217*795d594fSAndroid Build Coastguard Worker                                                          jint* new_class_data_len,
218*795d594fSAndroid Build Coastguard Worker                                                          unsigned char** new_class_data) const {
219*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
220*795d594fSAndroid Build Coastguard Worker   static_assert(kEvent == ArtJvmtiEvent::kClassFileLoadHookRetransformable ||
221*795d594fSAndroid Build Coastguard Worker                 kEvent == ArtJvmtiEvent::kClassFileLoadHookNonRetransformable ||
222*795d594fSAndroid Build Coastguard Worker                 kEvent == ArtJvmtiEvent::kStructuralDexFileLoadHook, "Unsupported event");
223*795d594fSAndroid Build Coastguard Worker   DCHECK(*new_class_data == nullptr);
224*795d594fSAndroid Build Coastguard Worker   jint current_len = class_data_len;
225*795d594fSAndroid Build Coastguard Worker   unsigned char* current_class_data = const_cast<unsigned char*>(class_data);
226*795d594fSAndroid Build Coastguard Worker   std::vector<impl::EventHandlerFunc<kEvent>> handlers =
227*795d594fSAndroid Build Coastguard Worker       CollectEvents<kEvent>(thread,
228*795d594fSAndroid Build Coastguard Worker                             jnienv,
229*795d594fSAndroid Build Coastguard Worker                             class_being_redefined,
230*795d594fSAndroid Build Coastguard Worker                             loader,
231*795d594fSAndroid Build Coastguard Worker                             name,
232*795d594fSAndroid Build Coastguard Worker                             protection_domain,
233*795d594fSAndroid Build Coastguard Worker                             class_data_len,
234*795d594fSAndroid Build Coastguard Worker                             class_data,
235*795d594fSAndroid Build Coastguard Worker                             new_class_data_len,
236*795d594fSAndroid Build Coastguard Worker                             new_class_data);
237*795d594fSAndroid Build Coastguard Worker   ArtJvmTiEnv* last_env = nullptr;
238*795d594fSAndroid Build Coastguard Worker   for (const impl::EventHandlerFunc<kEvent>& event : handlers) {
239*795d594fSAndroid Build Coastguard Worker     jint new_len = 0;
240*795d594fSAndroid Build Coastguard Worker     unsigned char* new_data = nullptr;
241*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<kEvent>(event,
242*795d594fSAndroid Build Coastguard Worker                             jnienv,
243*795d594fSAndroid Build Coastguard Worker                             class_being_redefined,
244*795d594fSAndroid Build Coastguard Worker                             loader,
245*795d594fSAndroid Build Coastguard Worker                             name,
246*795d594fSAndroid Build Coastguard Worker                             protection_domain,
247*795d594fSAndroid Build Coastguard Worker                             current_len,
248*795d594fSAndroid Build Coastguard Worker                             static_cast<const unsigned char*>(current_class_data),
249*795d594fSAndroid Build Coastguard Worker                             &new_len,
250*795d594fSAndroid Build Coastguard Worker                             &new_data);
251*795d594fSAndroid Build Coastguard Worker     if (new_data != nullptr && new_data != current_class_data) {
252*795d594fSAndroid Build Coastguard Worker       // Destroy the data the last transformer made. We skip this if the previous state was the
253*795d594fSAndroid Build Coastguard Worker       // initial one since we don't know here which jvmtiEnv allocated it.
254*795d594fSAndroid Build Coastguard Worker       // NB Currently this doesn't matter since all allocations just go to malloc but in the
255*795d594fSAndroid Build Coastguard Worker       // future we might have jvmtiEnv's keep track of their allocations for leak-checking.
256*795d594fSAndroid Build Coastguard Worker       if (last_env != nullptr) {
257*795d594fSAndroid Build Coastguard Worker         last_env->Deallocate(current_class_data);
258*795d594fSAndroid Build Coastguard Worker       }
259*795d594fSAndroid Build Coastguard Worker       last_env = event.env_;
260*795d594fSAndroid Build Coastguard Worker       current_class_data = new_data;
261*795d594fSAndroid Build Coastguard Worker       current_len = new_len;
262*795d594fSAndroid Build Coastguard Worker     }
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker   if (last_env != nullptr) {
265*795d594fSAndroid Build Coastguard Worker     *new_class_data_len = current_len;
266*795d594fSAndroid Build Coastguard Worker     *new_class_data = current_class_data;
267*795d594fSAndroid Build Coastguard Worker   }
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker // Our goal for DispatchEvent: Do not allow implicit type conversion. Types of ...args must match
271*795d594fSAndroid Build Coastguard Worker // exactly the argument types of the corresponding Jvmti kEvent function pointer.
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename ...Args>
DispatchEvent(art::Thread * thread,Args...args)274*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent(art::Thread* thread, Args... args) const {
275*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
276*795d594fSAndroid Build Coastguard Worker   static_assert(!std::is_same<JNIEnv*,
277*795d594fSAndroid Build Coastguard Worker                               typename std::decay_t<
278*795d594fSAndroid Build Coastguard Worker                                   std::tuple_element_t<0, std::tuple<Args..., nullptr_t>>>>::value,
279*795d594fSAndroid Build Coastguard Worker                 "Should be calling DispatchEvent with explicit JNIEnv* argument!");
280*795d594fSAndroid Build Coastguard Worker   DCHECK(thread == nullptr || !thread->IsExceptionPending());
281*795d594fSAndroid Build Coastguard Worker   std::vector<impl::EventHandlerFunc<kEvent>> events = CollectEvents<kEvent>(thread, args...);
282*795d594fSAndroid Build Coastguard Worker   for (auto event : events) {
283*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<kEvent>(event, args...);
284*795d594fSAndroid Build Coastguard Worker   }
285*795d594fSAndroid Build Coastguard Worker }
286*795d594fSAndroid Build Coastguard Worker 
287*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename ...Args>
DispatchEvent(art::Thread * thread,JNIEnv * jnienv,Args...args)288*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const {
289*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
290*795d594fSAndroid Build Coastguard Worker   std::vector<impl::EventHandlerFunc<kEvent>> events = CollectEvents<kEvent>(thread,
291*795d594fSAndroid Build Coastguard Worker                                                                              jnienv,
292*795d594fSAndroid Build Coastguard Worker                                                                              args...);
293*795d594fSAndroid Build Coastguard Worker   for (auto event : events) {
294*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<kEvent>(event, jnienv, args...);
295*795d594fSAndroid Build Coastguard Worker   }
296*795d594fSAndroid Build Coastguard Worker }
297*795d594fSAndroid Build Coastguard Worker 
298*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename ...Args>
DispatchEventOnEnv(ArtJvmTiEnv * env,art::Thread * thread,JNIEnv * jnienv,Args...args)299*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEventOnEnv(
300*795d594fSAndroid Build Coastguard Worker     ArtJvmTiEnv* env, art::Thread* thread, JNIEnv* jnienv, Args... args) const {
301*795d594fSAndroid Build Coastguard Worker   DCHECK(env != nullptr);
302*795d594fSAndroid Build Coastguard Worker   if (ShouldDispatch<kEvent, JNIEnv*, Args...>(env, thread, jnienv, args...)) {
303*795d594fSAndroid Build Coastguard Worker     art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
304*795d594fSAndroid Build Coastguard Worker     impl::EventHandlerFunc<kEvent> func(env);
305*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<kEvent>(func, jnienv, args...);
306*795d594fSAndroid Build Coastguard Worker   }
307*795d594fSAndroid Build Coastguard Worker }
308*795d594fSAndroid Build Coastguard Worker 
309*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename ...Args>
DispatchEventOnEnv(ArtJvmTiEnv * env,art::Thread * thread,Args...args)310*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEventOnEnv(
311*795d594fSAndroid Build Coastguard Worker     ArtJvmTiEnv* env, art::Thread* thread, Args... args) const {
312*795d594fSAndroid Build Coastguard Worker   static_assert(!std::is_same<JNIEnv*,
313*795d594fSAndroid Build Coastguard Worker                               typename std::decay_t<
314*795d594fSAndroid Build Coastguard Worker                                   std::tuple_element_t<0, std::tuple<Args..., nullptr_t>>>>::value,
315*795d594fSAndroid Build Coastguard Worker                 "Should be calling DispatchEventOnEnv with explicit JNIEnv* argument!");
316*795d594fSAndroid Build Coastguard Worker   DCHECK(env != nullptr);
317*795d594fSAndroid Build Coastguard Worker   if (ShouldDispatch<kEvent, Args...>(env, thread, args...)) {
318*795d594fSAndroid Build Coastguard Worker     art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
319*795d594fSAndroid Build Coastguard Worker     impl::EventHandlerFunc<kEvent> func(env);
320*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<kEvent>(func, args...);
321*795d594fSAndroid Build Coastguard Worker   }
322*795d594fSAndroid Build Coastguard Worker }
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker template <>
325*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEventOnEnv<ArtJvmtiEvent::kObsoleteObjectCreated>(
326*795d594fSAndroid Build Coastguard Worker     ArtJvmTiEnv* env, art::Thread* thread, jlong* obsolete_tag, jlong* new_tag) const {
327*795d594fSAndroid Build Coastguard Worker   static constexpr ArtJvmtiEvent kEvent = ArtJvmtiEvent::kObsoleteObjectCreated;
328*795d594fSAndroid Build Coastguard Worker   DCHECK(env != nullptr);
329*795d594fSAndroid Build Coastguard Worker   if (ShouldDispatch<kEvent>(env, thread, obsolete_tag, new_tag)) {
330*795d594fSAndroid Build Coastguard Worker     art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
331*795d594fSAndroid Build Coastguard Worker     impl::EventHandlerFunc<kEvent> func(env);
332*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<kEvent>(func, obsolete_tag, new_tag);
333*795d594fSAndroid Build Coastguard Worker   } else {
334*795d594fSAndroid Build Coastguard Worker     // Unlike most others this has a default action to make sure that agents without knowledge of
335*795d594fSAndroid Build Coastguard Worker     // this extension get reasonable behavior.
336*795d594fSAndroid Build Coastguard Worker     jlong temp = *obsolete_tag;
337*795d594fSAndroid Build Coastguard Worker     *obsolete_tag = *new_tag;
338*795d594fSAndroid Build Coastguard Worker     *new_tag = temp;
339*795d594fSAndroid Build Coastguard Worker   }
340*795d594fSAndroid Build Coastguard Worker }
341*795d594fSAndroid Build Coastguard Worker 
342*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename ...Args>
ExecuteCallback(impl::EventHandlerFunc<kEvent> handler,Args...args)343*795d594fSAndroid Build Coastguard Worker inline void EventHandler::ExecuteCallback(impl::EventHandlerFunc<kEvent> handler, Args... args) {
344*795d594fSAndroid Build Coastguard Worker   handler.ExecuteCallback(args...);
345*795d594fSAndroid Build Coastguard Worker }
346*795d594fSAndroid Build Coastguard Worker 
347*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename ...Args>
ExecuteCallback(impl::EventHandlerFunc<kEvent> handler,JNIEnv * jnienv,Args...args)348*795d594fSAndroid Build Coastguard Worker inline void EventHandler::ExecuteCallback(impl::EventHandlerFunc<kEvent> handler,
349*795d594fSAndroid Build Coastguard Worker                                           JNIEnv* jnienv,
350*795d594fSAndroid Build Coastguard Worker                                           Args... args) {
351*795d594fSAndroid Build Coastguard Worker   handler.ExecuteCallback(jnienv, args...);
352*795d594fSAndroid Build Coastguard Worker }
353*795d594fSAndroid Build Coastguard Worker 
354*795d594fSAndroid Build Coastguard Worker // Events that need custom logic for if we send the event but are otherwise normal. This includes
355*795d594fSAndroid Build Coastguard Worker // the kBreakpoint, kFramePop, kFieldAccess, and kFieldModification events.
356*795d594fSAndroid Build Coastguard Worker 
357*795d594fSAndroid Build Coastguard Worker // Need to give custom specializations for Breakpoint since it needs to filter out which particular
358*795d594fSAndroid Build Coastguard Worker // methods/dex_pcs agents get notified on.
359*795d594fSAndroid Build Coastguard Worker template <>
360*795d594fSAndroid Build Coastguard Worker inline bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kBreakpoint>(
361*795d594fSAndroid Build Coastguard Worker     ArtJvmTiEnv* env,
362*795d594fSAndroid Build Coastguard Worker     art::Thread* thread,
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] JNIEnv* jnienv,
365*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jthread jni_thread,
366*795d594fSAndroid Build Coastguard Worker     jmethodID jmethod,
367*795d594fSAndroid Build Coastguard Worker     jlocation location) const {
368*795d594fSAndroid Build Coastguard Worker   art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
369*795d594fSAndroid Build Coastguard Worker   art::ArtMethod* method = art::jni::DecodeArtMethod(jmethod);
370*795d594fSAndroid Build Coastguard Worker   return ShouldDispatchOnThread<ArtJvmtiEvent::kBreakpoint>(env, thread) &&
371*795d594fSAndroid Build Coastguard Worker       env->breakpoints.find({method, location}) != env->breakpoints.end();
372*795d594fSAndroid Build Coastguard Worker }
373*795d594fSAndroid Build Coastguard Worker 
374*795d594fSAndroid Build Coastguard Worker template <>
375*795d594fSAndroid Build Coastguard Worker inline bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kFramePop>(
376*795d594fSAndroid Build Coastguard Worker     ArtJvmTiEnv* env,
377*795d594fSAndroid Build Coastguard Worker     art::Thread* thread,
378*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] JNIEnv* jnienv,
379*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jthread jni_thread,
380*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jmethodID jmethod,
381*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jboolean is_exception,
382*795d594fSAndroid Build Coastguard Worker     const art::ShadowFrame* frame) const {
383*795d594fSAndroid Build Coastguard Worker   // Search for the frame. Do this before checking if we need to send the event so that we don't
384*795d594fSAndroid Build Coastguard Worker   // have to deal with use-after-free or the frames being reallocated later.
385*795d594fSAndroid Build Coastguard Worker   art::WriterMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
386*795d594fSAndroid Build Coastguard Worker   return env->notify_frames.erase(frame) != 0 &&
387*795d594fSAndroid Build Coastguard Worker       !frame->GetSkipMethodExitEvents() &&
388*795d594fSAndroid Build Coastguard Worker       ShouldDispatchOnThread<ArtJvmtiEvent::kFramePop>(env, thread);
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker 
391*795d594fSAndroid Build Coastguard Worker // Need to give custom specializations for FieldAccess and FieldModification since they need to
392*795d594fSAndroid Build Coastguard Worker // filter out which particular fields agents want to get notified on.
393*795d594fSAndroid Build Coastguard Worker // TODO The spec allows us to do shortcuts like only allow one agent to ever set these watches. This
394*795d594fSAndroid Build Coastguard Worker // could make the system more performant.
395*795d594fSAndroid Build Coastguard Worker template <>
396*795d594fSAndroid Build Coastguard Worker inline bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kFieldModification>(
397*795d594fSAndroid Build Coastguard Worker     ArtJvmTiEnv* env,
398*795d594fSAndroid Build Coastguard Worker     art::Thread* thread,
399*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] JNIEnv* jnienv,
400*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jthread jni_thread,
401*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jmethodID method,
402*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jlocation location,
403*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jclass field_klass,
404*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jobject object,
405*795d594fSAndroid Build Coastguard Worker     jfieldID field,
406*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] char type_char,
407*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jvalue val) const {
408*795d594fSAndroid Build Coastguard Worker   art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
409*795d594fSAndroid Build Coastguard Worker   return ShouldDispatchOnThread<ArtJvmtiEvent::kFieldModification>(env, thread) &&
410*795d594fSAndroid Build Coastguard Worker       env->modify_watched_fields.find(
411*795d594fSAndroid Build Coastguard Worker           art::jni::DecodeArtField(field)) != env->modify_watched_fields.end();
412*795d594fSAndroid Build Coastguard Worker }
413*795d594fSAndroid Build Coastguard Worker 
414*795d594fSAndroid Build Coastguard Worker template <>
415*795d594fSAndroid Build Coastguard Worker inline bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kFieldAccess>(
416*795d594fSAndroid Build Coastguard Worker     ArtJvmTiEnv* env,
417*795d594fSAndroid Build Coastguard Worker     art::Thread* thread,
418*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] JNIEnv* jnienv,
419*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jthread jni_thread,
420*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jmethodID method,
421*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jlocation location,
422*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jclass field_klass,
423*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] jobject object,
424*795d594fSAndroid Build Coastguard Worker     jfieldID field) const {
425*795d594fSAndroid Build Coastguard Worker   art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
426*795d594fSAndroid Build Coastguard Worker   return ShouldDispatchOnThread<ArtJvmtiEvent::kFieldAccess>(env, thread) &&
427*795d594fSAndroid Build Coastguard Worker       env->access_watched_fields.find(
428*795d594fSAndroid Build Coastguard Worker           art::jni::DecodeArtField(field)) != env->access_watched_fields.end();
429*795d594fSAndroid Build Coastguard Worker }
430*795d594fSAndroid Build Coastguard Worker 
431*795d594fSAndroid Build Coastguard Worker // Need to give custom specializations for FramePop since it needs to filter out which particular
432*795d594fSAndroid Build Coastguard Worker // agents get the event. This specialization gets an extra argument so we can determine which (if
433*795d594fSAndroid Build Coastguard Worker // any) environments have the frame pop.
434*795d594fSAndroid Build Coastguard Worker // TODO It might be useful to use more template magic to have this only define ShouldDispatch or
435*795d594fSAndroid Build Coastguard Worker // something.
436*795d594fSAndroid Build Coastguard Worker template <>
437*795d594fSAndroid Build Coastguard Worker inline void EventHandler::ExecuteCallback<ArtJvmtiEvent::kFramePop>(
438*795d594fSAndroid Build Coastguard Worker     impl::EventHandlerFunc<ArtJvmtiEvent::kFramePop> event,
439*795d594fSAndroid Build Coastguard Worker     JNIEnv* jnienv,
440*795d594fSAndroid Build Coastguard Worker     jthread jni_thread,
441*795d594fSAndroid Build Coastguard Worker     jmethodID jmethod,
442*795d594fSAndroid Build Coastguard Worker     jboolean is_exception,
443*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] const art::ShadowFrame* frame) {
444*795d594fSAndroid Build Coastguard Worker   ExecuteCallback<ArtJvmtiEvent::kFramePop>(event, jnienv, jni_thread, jmethod, is_exception);
445*795d594fSAndroid Build Coastguard Worker }
446*795d594fSAndroid Build Coastguard Worker 
447*795d594fSAndroid Build Coastguard Worker struct ScopedDisablePopFrame {
448*795d594fSAndroid Build Coastguard Worker  public:
ScopedDisablePopFrameScopedDisablePopFrame449*795d594fSAndroid Build Coastguard Worker   explicit ScopedDisablePopFrame(art::Thread* thread) : thread_(thread) {
450*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(thread_);
451*795d594fSAndroid Build Coastguard Worker     art::MutexLock mu(thread_, *art::Locks::thread_list_lock_);
452*795d594fSAndroid Build Coastguard Worker     JvmtiGlobalTLSData* data = ThreadUtil::GetOrCreateGlobalTLSData(thread_);
453*795d594fSAndroid Build Coastguard Worker     current_top_frame_ = art::StackVisitor::ComputeNumFrames(
454*795d594fSAndroid Build Coastguard Worker         thread_, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
455*795d594fSAndroid Build Coastguard Worker     old_disable_frame_pop_depth_ = data->disable_pop_frame_depth;
456*795d594fSAndroid Build Coastguard Worker     data->disable_pop_frame_depth = current_top_frame_;
457*795d594fSAndroid Build Coastguard Worker     // Check that we cleaned up any old disables. This should only increase (or be equals if we do
458*795d594fSAndroid Build Coastguard Worker     // another ClassLoad/Prepare recursively).
459*795d594fSAndroid Build Coastguard Worker     DCHECK(old_disable_frame_pop_depth_ == JvmtiGlobalTLSData::kNoDisallowedPopFrame ||
460*795d594fSAndroid Build Coastguard Worker            current_top_frame_ >= old_disable_frame_pop_depth_)
461*795d594fSAndroid Build Coastguard Worker         << "old: " << old_disable_frame_pop_depth_ << " current: " << current_top_frame_;
462*795d594fSAndroid Build Coastguard Worker   }
463*795d594fSAndroid Build Coastguard Worker 
~ScopedDisablePopFrameScopedDisablePopFrame464*795d594fSAndroid Build Coastguard Worker   ~ScopedDisablePopFrame() {
465*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(thread_);
466*795d594fSAndroid Build Coastguard Worker     art::MutexLock mu(thread_, *art::Locks::thread_list_lock_);
467*795d594fSAndroid Build Coastguard Worker     JvmtiGlobalTLSData* data = ThreadUtil::GetGlobalTLSData(thread_);
468*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(data->disable_pop_frame_depth, current_top_frame_);
469*795d594fSAndroid Build Coastguard Worker     data->disable_pop_frame_depth = old_disable_frame_pop_depth_;
470*795d594fSAndroid Build Coastguard Worker   }
471*795d594fSAndroid Build Coastguard Worker 
472*795d594fSAndroid Build Coastguard Worker  private:
473*795d594fSAndroid Build Coastguard Worker   art::Thread* thread_;
474*795d594fSAndroid Build Coastguard Worker   size_t current_top_frame_;
475*795d594fSAndroid Build Coastguard Worker   size_t old_disable_frame_pop_depth_;
476*795d594fSAndroid Build Coastguard Worker };
477*795d594fSAndroid Build Coastguard Worker // We want to prevent the use of PopFrame when reporting either of these events.
478*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent>
DispatchClassLoadOrPrepareEvent(art::Thread * thread,JNIEnv * jnienv,jthread jni_thread,jclass klass)479*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchClassLoadOrPrepareEvent(art::Thread* thread,
480*795d594fSAndroid Build Coastguard Worker                                                           JNIEnv* jnienv,
481*795d594fSAndroid Build Coastguard Worker                                                           jthread jni_thread,
482*795d594fSAndroid Build Coastguard Worker                                                           jclass klass) const {
483*795d594fSAndroid Build Coastguard Worker   ScopedDisablePopFrame sdpf(thread);
484*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
485*795d594fSAndroid Build Coastguard Worker   std::vector<impl::EventHandlerFunc<kEvent>> events = CollectEvents<kEvent>(thread,
486*795d594fSAndroid Build Coastguard Worker                                                                              jnienv,
487*795d594fSAndroid Build Coastguard Worker                                                                              jni_thread,
488*795d594fSAndroid Build Coastguard Worker                                                                              klass);
489*795d594fSAndroid Build Coastguard Worker 
490*795d594fSAndroid Build Coastguard Worker   for (auto event : events) {
491*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<kEvent>(event, jnienv, jni_thread, klass);
492*795d594fSAndroid Build Coastguard Worker   }
493*795d594fSAndroid Build Coastguard Worker }
494*795d594fSAndroid Build Coastguard Worker 
495*795d594fSAndroid Build Coastguard Worker template <>
496*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassLoad>(art::Thread* thread,
497*795d594fSAndroid Build Coastguard Worker                                                                    JNIEnv* jnienv,
498*795d594fSAndroid Build Coastguard Worker                                                                    jthread jni_thread,
499*795d594fSAndroid Build Coastguard Worker                                                                    jclass klass) const {
500*795d594fSAndroid Build Coastguard Worker   DispatchClassLoadOrPrepareEvent<ArtJvmtiEvent::kClassLoad>(thread, jnienv, jni_thread, klass);
501*795d594fSAndroid Build Coastguard Worker }
502*795d594fSAndroid Build Coastguard Worker template <>
503*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassPrepare>(art::Thread* thread,
504*795d594fSAndroid Build Coastguard Worker                                                                       JNIEnv* jnienv,
505*795d594fSAndroid Build Coastguard Worker                                                                       jthread jni_thread,
506*795d594fSAndroid Build Coastguard Worker                                                                       jclass klass) const {
507*795d594fSAndroid Build Coastguard Worker   DispatchClassLoadOrPrepareEvent<ArtJvmtiEvent::kClassPrepare>(thread, jnienv, jni_thread, klass);
508*795d594fSAndroid Build Coastguard Worker }
509*795d594fSAndroid Build Coastguard Worker 
510*795d594fSAndroid Build Coastguard Worker // Need to give a custom specialization for NativeMethodBind since it has to deal with an out
511*795d594fSAndroid Build Coastguard Worker // variable.
512*795d594fSAndroid Build Coastguard Worker template <>
513*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(art::Thread* thread,
514*795d594fSAndroid Build Coastguard Worker                                                                           JNIEnv* jnienv,
515*795d594fSAndroid Build Coastguard Worker                                                                           jthread jni_thread,
516*795d594fSAndroid Build Coastguard Worker                                                                           jmethodID method,
517*795d594fSAndroid Build Coastguard Worker                                                                           void* cur_method,
518*795d594fSAndroid Build Coastguard Worker                                                                           void** new_method) const {
519*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
520*795d594fSAndroid Build Coastguard Worker   std::vector<impl::EventHandlerFunc<ArtJvmtiEvent::kNativeMethodBind>> events =
521*795d594fSAndroid Build Coastguard Worker       CollectEvents<ArtJvmtiEvent::kNativeMethodBind>(thread,
522*795d594fSAndroid Build Coastguard Worker                                                       jnienv,
523*795d594fSAndroid Build Coastguard Worker                                                       jni_thread,
524*795d594fSAndroid Build Coastguard Worker                                                       method,
525*795d594fSAndroid Build Coastguard Worker                                                       cur_method,
526*795d594fSAndroid Build Coastguard Worker                                                       new_method);
527*795d594fSAndroid Build Coastguard Worker   *new_method = cur_method;
528*795d594fSAndroid Build Coastguard Worker   for (auto event : events) {
529*795d594fSAndroid Build Coastguard Worker     *new_method = cur_method;
530*795d594fSAndroid Build Coastguard Worker     ExecuteCallback<ArtJvmtiEvent::kNativeMethodBind>(event,
531*795d594fSAndroid Build Coastguard Worker                                                       jnienv,
532*795d594fSAndroid Build Coastguard Worker                                                       jni_thread,
533*795d594fSAndroid Build Coastguard Worker                                                       method,
534*795d594fSAndroid Build Coastguard Worker                                                       cur_method,
535*795d594fSAndroid Build Coastguard Worker                                                       new_method);
536*795d594fSAndroid Build Coastguard Worker     if (*new_method != nullptr) {
537*795d594fSAndroid Build Coastguard Worker       cur_method = *new_method;
538*795d594fSAndroid Build Coastguard Worker     }
539*795d594fSAndroid Build Coastguard Worker   }
540*795d594fSAndroid Build Coastguard Worker   *new_method = cur_method;
541*795d594fSAndroid Build Coastguard Worker }
542*795d594fSAndroid Build Coastguard Worker 
543*795d594fSAndroid Build Coastguard Worker // C++ does not allow partial template function specialization. The dispatch for our separated
544*795d594fSAndroid Build Coastguard Worker // ClassFileLoadHook event types is the same, and in the DispatchClassFileLoadHookEvent helper.
545*795d594fSAndroid Build Coastguard Worker // The following two DispatchEvent specializations dispatch to it.
546*795d594fSAndroid Build Coastguard Worker template <>
547*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
548*795d594fSAndroid Build Coastguard Worker     art::Thread* thread,
549*795d594fSAndroid Build Coastguard Worker     JNIEnv* jnienv,
550*795d594fSAndroid Build Coastguard Worker     jclass class_being_redefined,
551*795d594fSAndroid Build Coastguard Worker     jobject loader,
552*795d594fSAndroid Build Coastguard Worker     const char* name,
553*795d594fSAndroid Build Coastguard Worker     jobject protection_domain,
554*795d594fSAndroid Build Coastguard Worker     jint class_data_len,
555*795d594fSAndroid Build Coastguard Worker     const unsigned char* class_data,
556*795d594fSAndroid Build Coastguard Worker     jint* new_class_data_len,
557*795d594fSAndroid Build Coastguard Worker     unsigned char** new_class_data) const {
558*795d594fSAndroid Build Coastguard Worker   return DispatchClassFileLoadHookEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
559*795d594fSAndroid Build Coastguard Worker       thread,
560*795d594fSAndroid Build Coastguard Worker       jnienv,
561*795d594fSAndroid Build Coastguard Worker       class_being_redefined,
562*795d594fSAndroid Build Coastguard Worker       loader,
563*795d594fSAndroid Build Coastguard Worker       name,
564*795d594fSAndroid Build Coastguard Worker       protection_domain,
565*795d594fSAndroid Build Coastguard Worker       class_data_len,
566*795d594fSAndroid Build Coastguard Worker       class_data,
567*795d594fSAndroid Build Coastguard Worker       new_class_data_len,
568*795d594fSAndroid Build Coastguard Worker       new_class_data);
569*795d594fSAndroid Build Coastguard Worker }
570*795d594fSAndroid Build Coastguard Worker 
571*795d594fSAndroid Build Coastguard Worker template <>
572*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(
573*795d594fSAndroid Build Coastguard Worker     art::Thread* thread,
574*795d594fSAndroid Build Coastguard Worker     JNIEnv* jnienv,
575*795d594fSAndroid Build Coastguard Worker     jclass class_being_redefined,
576*795d594fSAndroid Build Coastguard Worker     jobject loader,
577*795d594fSAndroid Build Coastguard Worker     const char* name,
578*795d594fSAndroid Build Coastguard Worker     jobject protection_domain,
579*795d594fSAndroid Build Coastguard Worker     jint class_data_len,
580*795d594fSAndroid Build Coastguard Worker     const unsigned char* class_data,
581*795d594fSAndroid Build Coastguard Worker     jint* new_class_data_len,
582*795d594fSAndroid Build Coastguard Worker     unsigned char** new_class_data) const {
583*795d594fSAndroid Build Coastguard Worker   return DispatchClassFileLoadHookEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(
584*795d594fSAndroid Build Coastguard Worker       thread,
585*795d594fSAndroid Build Coastguard Worker       jnienv,
586*795d594fSAndroid Build Coastguard Worker       class_being_redefined,
587*795d594fSAndroid Build Coastguard Worker       loader,
588*795d594fSAndroid Build Coastguard Worker       name,
589*795d594fSAndroid Build Coastguard Worker       protection_domain,
590*795d594fSAndroid Build Coastguard Worker       class_data_len,
591*795d594fSAndroid Build Coastguard Worker       class_data,
592*795d594fSAndroid Build Coastguard Worker       new_class_data_len,
593*795d594fSAndroid Build Coastguard Worker       new_class_data);
594*795d594fSAndroid Build Coastguard Worker }
595*795d594fSAndroid Build Coastguard Worker 
596*795d594fSAndroid Build Coastguard Worker template <>
597*795d594fSAndroid Build Coastguard Worker inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kStructuralDexFileLoadHook>(
598*795d594fSAndroid Build Coastguard Worker     art::Thread* thread,
599*795d594fSAndroid Build Coastguard Worker     JNIEnv* jnienv,
600*795d594fSAndroid Build Coastguard Worker     jclass class_being_redefined,
601*795d594fSAndroid Build Coastguard Worker     jobject loader,
602*795d594fSAndroid Build Coastguard Worker     const char* name,
603*795d594fSAndroid Build Coastguard Worker     jobject protection_domain,
604*795d594fSAndroid Build Coastguard Worker     jint class_data_len,
605*795d594fSAndroid Build Coastguard Worker     const unsigned char* class_data,
606*795d594fSAndroid Build Coastguard Worker     jint* new_class_data_len,
607*795d594fSAndroid Build Coastguard Worker     unsigned char** new_class_data) const {
608*795d594fSAndroid Build Coastguard Worker   return DispatchClassFileLoadHookEvent<ArtJvmtiEvent::kStructuralDexFileLoadHook>(
609*795d594fSAndroid Build Coastguard Worker       thread,
610*795d594fSAndroid Build Coastguard Worker       jnienv,
611*795d594fSAndroid Build Coastguard Worker       class_being_redefined,
612*795d594fSAndroid Build Coastguard Worker       loader,
613*795d594fSAndroid Build Coastguard Worker       name,
614*795d594fSAndroid Build Coastguard Worker       protection_domain,
615*795d594fSAndroid Build Coastguard Worker       class_data_len,
616*795d594fSAndroid Build Coastguard Worker       class_data,
617*795d594fSAndroid Build Coastguard Worker       new_class_data_len,
618*795d594fSAndroid Build Coastguard Worker       new_class_data);
619*795d594fSAndroid Build Coastguard Worker }
620*795d594fSAndroid Build Coastguard Worker 
621*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent>
ShouldDispatchOnThread(ArtJvmTiEnv * env,art::Thread * thread)622*795d594fSAndroid Build Coastguard Worker inline bool EventHandler::ShouldDispatchOnThread(ArtJvmTiEnv* env, art::Thread* thread) const {
623*795d594fSAndroid Build Coastguard Worker   bool dispatch = env->event_masks.global_event_mask.Test(kEvent);
624*795d594fSAndroid Build Coastguard Worker 
625*795d594fSAndroid Build Coastguard Worker   if (!dispatch && thread != nullptr && env->event_masks.unioned_thread_event_mask.Test(kEvent)) {
626*795d594fSAndroid Build Coastguard Worker     EventMask* mask = env->event_masks.GetEventMaskOrNull(thread);
627*795d594fSAndroid Build Coastguard Worker     dispatch = mask != nullptr && mask->Test(kEvent);
628*795d594fSAndroid Build Coastguard Worker   }
629*795d594fSAndroid Build Coastguard Worker   return dispatch;
630*795d594fSAndroid Build Coastguard Worker }
631*795d594fSAndroid Build Coastguard Worker 
632*795d594fSAndroid Build Coastguard Worker template <ArtJvmtiEvent kEvent, typename... Args>
ShouldDispatch(ArtJvmTiEnv * env,art::Thread * thread,Args...args)633*795d594fSAndroid Build Coastguard Worker inline bool EventHandler::ShouldDispatch(ArtJvmTiEnv* env,
634*795d594fSAndroid Build Coastguard Worker                                          art::Thread* thread,
635*795d594fSAndroid Build Coastguard Worker                                          [[maybe_unused]] Args... args) const {
636*795d594fSAndroid Build Coastguard Worker   static_assert(std::is_same<typename impl::EventFnType<kEvent>::type,
637*795d594fSAndroid Build Coastguard Worker                              void(*)(jvmtiEnv*, Args...)>::value,
638*795d594fSAndroid Build Coastguard Worker                 "Unexpected different type of shouldDispatch");
639*795d594fSAndroid Build Coastguard Worker 
640*795d594fSAndroid Build Coastguard Worker   return ShouldDispatchOnThread<kEvent>(env, thread);
641*795d594fSAndroid Build Coastguard Worker }
642*795d594fSAndroid Build Coastguard Worker 
RecalculateGlobalEventMask(ArtJvmtiEvent event)643*795d594fSAndroid Build Coastguard Worker inline void EventHandler::RecalculateGlobalEventMask(ArtJvmtiEvent event) {
644*795d594fSAndroid Build Coastguard Worker   art::WriterMutexLock mu(art::Thread::Current(), envs_lock_);
645*795d594fSAndroid Build Coastguard Worker   RecalculateGlobalEventMaskLocked(event);
646*795d594fSAndroid Build Coastguard Worker }
647*795d594fSAndroid Build Coastguard Worker 
RecalculateGlobalEventMaskLocked(ArtJvmtiEvent event)648*795d594fSAndroid Build Coastguard Worker inline void EventHandler::RecalculateGlobalEventMaskLocked(ArtJvmtiEvent event) {
649*795d594fSAndroid Build Coastguard Worker   bool union_value = false;
650*795d594fSAndroid Build Coastguard Worker   for (const ArtJvmTiEnv* stored_env : envs) {
651*795d594fSAndroid Build Coastguard Worker     if (stored_env == nullptr) {
652*795d594fSAndroid Build Coastguard Worker       continue;
653*795d594fSAndroid Build Coastguard Worker     }
654*795d594fSAndroid Build Coastguard Worker     union_value |= stored_env->event_masks.global_event_mask.Test(event);
655*795d594fSAndroid Build Coastguard Worker     union_value |= stored_env->event_masks.unioned_thread_event_mask.Test(event);
656*795d594fSAndroid Build Coastguard Worker     if (union_value) {
657*795d594fSAndroid Build Coastguard Worker       break;
658*795d594fSAndroid Build Coastguard Worker     }
659*795d594fSAndroid Build Coastguard Worker   }
660*795d594fSAndroid Build Coastguard Worker   global_mask.Set(event, union_value);
661*795d594fSAndroid Build Coastguard Worker }
662*795d594fSAndroid Build Coastguard Worker 
NeedsEventUpdate(ArtJvmTiEnv * env,const jvmtiCapabilities & caps,bool added)663*795d594fSAndroid Build Coastguard Worker inline bool EventHandler::NeedsEventUpdate(ArtJvmTiEnv* env,
664*795d594fSAndroid Build Coastguard Worker                                            const jvmtiCapabilities& caps,
665*795d594fSAndroid Build Coastguard Worker                                            bool added) {
666*795d594fSAndroid Build Coastguard Worker   ArtJvmtiEvent event = added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
667*795d594fSAndroid Build Coastguard Worker                               : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
668*795d594fSAndroid Build Coastguard Worker   return (added && caps.can_access_local_variables == 1) ||
669*795d594fSAndroid Build Coastguard Worker       caps.can_generate_breakpoint_events == 1 ||
670*795d594fSAndroid Build Coastguard Worker       caps.can_pop_frame == 1 ||
671*795d594fSAndroid Build Coastguard Worker       caps.can_force_early_return == 1 ||
672*795d594fSAndroid Build Coastguard Worker       (caps.can_retransform_classes == 1 &&
673*795d594fSAndroid Build Coastguard Worker        IsEventEnabledAnywhere(event) &&
674*795d594fSAndroid Build Coastguard Worker        env->event_masks.IsEnabledAnywhere(event));
675*795d594fSAndroid Build Coastguard Worker }
676*795d594fSAndroid Build Coastguard Worker 
HandleChangedCapabilities(ArtJvmTiEnv * env,const jvmtiCapabilities & caps,bool added)677*795d594fSAndroid Build Coastguard Worker inline void EventHandler::HandleChangedCapabilities(ArtJvmTiEnv* env,
678*795d594fSAndroid Build Coastguard Worker                                                     const jvmtiCapabilities& caps,
679*795d594fSAndroid Build Coastguard Worker                                                     bool added) {
680*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(NeedsEventUpdate(env, caps, added))) {
681*795d594fSAndroid Build Coastguard Worker     env->event_masks.HandleChangedCapabilities(caps, added);
682*795d594fSAndroid Build Coastguard Worker     if (caps.can_retransform_classes == 1) {
683*795d594fSAndroid Build Coastguard Worker       RecalculateGlobalEventMask(ArtJvmtiEvent::kClassFileLoadHookRetransformable);
684*795d594fSAndroid Build Coastguard Worker       RecalculateGlobalEventMask(ArtJvmtiEvent::kClassFileLoadHookNonRetransformable);
685*795d594fSAndroid Build Coastguard Worker     }
686*795d594fSAndroid Build Coastguard Worker     if (added && caps.can_access_local_variables == 1) {
687*795d594fSAndroid Build Coastguard Worker       HandleLocalAccessCapabilityAdded();
688*795d594fSAndroid Build Coastguard Worker     }
689*795d594fSAndroid Build Coastguard Worker     if (caps.can_generate_breakpoint_events == 1) {
690*795d594fSAndroid Build Coastguard Worker       HandleBreakpointEventsChanged(added);
691*795d594fSAndroid Build Coastguard Worker     }
692*795d594fSAndroid Build Coastguard Worker     if ((caps.can_pop_frame == 1 || caps.can_force_early_return == 1) && added) {
693*795d594fSAndroid Build Coastguard Worker       // TODO We should keep track of how many of these have been enabled and remove it if there are
694*795d594fSAndroid Build Coastguard Worker       // no more possible users. This isn't expected to be too common.
695*795d594fSAndroid Build Coastguard Worker       art::Runtime::Current()->SetNonStandardExitsEnabled();
696*795d594fSAndroid Build Coastguard Worker     }
697*795d594fSAndroid Build Coastguard Worker   }
698*795d594fSAndroid Build Coastguard Worker }
699*795d594fSAndroid Build Coastguard Worker 
700*795d594fSAndroid Build Coastguard Worker }  // namespace openjdkjvmti
701*795d594fSAndroid Build Coastguard Worker 
702*795d594fSAndroid Build Coastguard Worker #endif  // ART_OPENJDKJVMTI_EVENTS_INL_H_
703