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